覆盖中的几个基本问题
我的基本功能没有什么问题,如果有人能解决这个问题,我将不胜感激。
1:当我说 base *b 时是什么意思 =新派生;为什么要这么做呢?我们很好分开 为类基创建对象并 派生类,然后调用 相应地发挥作用。我知道 这个基 *b = 新派生的;是 称为对象切片,但为什么和 人们什么时候会这样做呢?
2:我知道 为什么不建议转换 要派生的基类对象 类对象(因为基类是 不知道派生类 成员和方法)。我什至读过 其他 StackOverflow 线程,如果 那么我们就会这样 必须改变/重新访问我们的设计。 我明白这一切,但是,我 只是好奇,有什么办法吗 这?
class base
{
public:
void f(){cout << "In Base";}
};
class derived:public base
{
public:
void f(){cout << "In Derived";}
};
int _tmain(int argc, _TCHAR* argv[])
{
base b1, b2;
derived d1, d2;
b2 = d1;
d2 = reinterpret_cast<derived*>(b1); //gives error C2440
b1.f(); // Prints In Base
d1.f(); // Prints In Derived
b2.f(); // Prints In Base
d1.base::f(); //Prints In Base
d2.f();
getch();
return 0;
}
3:在上面的示例中,有什么方法可以使用派生类对象调用基类 f() 吗?我使用 d1.base()::f() 我只是想知道是否有任何方法不使用范围解析运算符?
非常感谢您花时间帮助我!
I have few problems with my basic and would be thankful if someone can clear this.
1: What does it mean when I say base *b
= new derived; Why would one go for this? We very well separately can
create objects for class base and
class derived and then call the
functions accordingly. I know that
this base *b = new derived; is
called as Object Slicing but why and
when would one go for this?
2: I know
why it is not advisable to convert
the base class object to derived
class object (because base class is
not aware of the derived class
members and methods). I even read in
other StackOverflow threads that if
this is gonna be the case then we
have to change/re-visit our design.
I understand all that, however, I am
just curious, Is there any way to do
this?
class base
{
public:
void f(){cout << "In Base";}
};
class derived:public base
{
public:
void f(){cout << "In Derived";}
};
int _tmain(int argc, _TCHAR* argv[])
{
base b1, b2;
derived d1, d2;
b2 = d1;
d2 = reinterpret_cast<derived*>(b1); //gives error C2440
b1.f(); // Prints In Base
d1.f(); // Prints In Derived
b2.f(); // Prints In Base
d1.base::f(); //Prints In Base
d2.f();
getch();
return 0;
}
3: In case of my above example, is there any way I could call the base class f() using derived class object? I used d1.base()::f() I just want to know if there any way without using scope resolution operator?
Thanks a lot for your time in helping me out!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
1.这不是对象切片:
这是将
base
类型的指针分配给衍生
的实例。一个(非常常见的)例子是回调。考虑一下:
这应该是预期的输出:
注意这里发生了什么。我们将一个指向
MyObserver
实例的指针传递给SetObserver()
,即使该函数只接受Observer
类型的指针。这是有效的,因为MyObserver
(公开)派生自Observer
。在这种情况下,我们说MyObserver
is-anObserver
。Observer
类型定义一个纯虚函数(=0
表示该函数是纯函数;它必须由派生类实现)。virtual
关键字告诉编译器调用该函数应该导致执行最接近的派生函数。MyObserver
中的OnEvent()
函数是最派生的,因此,即使我们在以下位置调用OnEvent()
,也会调用该版本:Observer
类型的指针。我们经历了所有这一切的麻烦,因为在这段代码中,
Subject
不必知道其观察者的确切类型 - 观察者只需要从Observer
派生并且Subject
实例将调用OnEvent()
的最派生类型的实现。这允许代码解耦 -Subject
不依赖于MyObserver
,并且MyObserver
不依赖于Subject
。2.将指针从基类转换为派生类型本身并没有什么问题。以下内容实际上是合法的,并且保证可以工作:
但是,此代码片段中的 return 语句之前的行是未定义的:
d2p
指针的值是没有意义的,尝试访问其中的任何内容都会肯定会导致崩溃,因为bp
指针实际上并不指向Derived2
实例,它指向Derived1
实例。编译器无法在编译时捕获这一点,因为Derived1
和Derived2
都继承自Base
,因此强制转换可以成功编译。这是从基类型转换为派生类型的主要危险 - 直到运行时您才会知道转换是否实际上返回有意义的结果。当然,除非您使用
dynamic_cast<>()
,但强制转换会导致运行时损失。static_cast<>()
最多涉及指针运算。reinterpret_cast<>()
强制指针采用不同的(可能不相关的)类型,而不执行任何指针算术。这使得reinterpret_cast<>()
成为更危险的强制转换之一,并且应该仅在必要时使用,特别是当static_cast<>()
可以完成这项工作时。3. 考虑以下事项:
如果
Foobar()
函数不是虚拟的,那么您将得到以下输出:否则,如果
Foobar()
> 函数是虚拟的,那么您将得到以下输出:为了保证对虚拟函数 Foobar() 的调用通过基指针调用基本实现,您必须使用作用域解析运算符:
1. This is not object slicing:
This is assigning a pointer of type
base
to an instance ofderived
.One (very common) example of this in action is in callbacks. Consider this:
This should be the expected output:
Notice what is happening here. We're passing in a pointer to an instance of
MyObserver
toSetObserver()
even though the function only accepts pointers of typeObserver
. This works becauseMyObserver
(publicly) derives fromObserver
. In this case, we say thatMyObserver
is-anObserver
.The
Observer
type defines a pure virtual function (The=0
means that the function is pure; it must be implemented by derived classes). Thevirtual
keyword tells the compiler that calling the function should cause the most-derived function to be executed. TheOnEvent()
function inMyObserver
is the most-derived, therefore, that version is called, even though we are callingOnEvent()
on a pointer of typeObserver
.We go through the trouble of doing all this because in this code
Subject
doesn't have to know the exact type of its observer - the observers just have to derive fromObserver
and theSubject
instance will call the most derived type's implementation ofOnEvent()
. This allows for code decoupling -Subject
doesn't depend onMyObserver
, andMyObserver
doesn't depend onSubject
.2. There's nothing wrong with casting a pointer from a base to derived type per se. The following is in fact legal and guaranteed to work:
The line before the return statement in this snippet, however, is undefined:
The value of the
d2p
pointer is meaningless, and attempting to access anything in it will certainly cause a crash, because thebp
pointer doesn't actually point to aDerived2
instance, it points to aDerived1
instance. Compilers cannot catch this at compile time, because bothDerived1
andDerived2
inherit fromBase
, so the cast successfully compiles. This is the main danger with casting from a base to a derived type - you won't know until runtime if the cast actually returns meaningful results.Of course, unless you use
dynamic_cast<>()
, but the cast incurs a runtime penalty.static_cast<>()
involves at most, pointer arithmetic.reinterpret_cast<>()
forces a pointer to take on a different (potentially unrelated) type, without performing any pointer arithmetic. This makesreinterpret_cast<>()
one of the more dangerous casts and should be used only when necessary, especially ifstatic_cast<>()
can do the job.3. Consider the following:
If the
Foobar()
function is not virtual, then you will get this output:Otherwise, if the
Foobar()
function is virtual, then you will get this output:To guarantee that a call to the virtual function
Foobar()
invokes the base implementation via the base pointer, then you have to use the scope resolution operator:是和不是。你可以走了
派生类:公共基础{
公共:无效f(){基点::f(); }
不过,
我在全球范围内不太确定。
Yes and no. You can go
class derived: public base {
public: void f() { base::f(); }
};
I'm not too sure about at a global scope though.
问题 1:为什么要这样做:您可能不会直接这样做。发生这种情况的情况是,例如,您有一个返回“某种基数*”的函数,而您不关心是哪种类型。
问题2:在派生类中,您需要使用范围解析运算符来指定您要使用基类的实现。
注意:您还没有将函数声明为虚拟的,因此您实际上不会获得您期望的行为。
Question 1: Why would you do this: you probably wouldn't do this directly. The case where this would happen would be where you had, for example, a function that returns "some kind of base*" and you don't care which type.
Question2: from within derived, you need to use the scope resolution operator to specify that you want to use the base class' implementation.
Note: you have not declared your function virtual, so you are not actually going to get the behavior you are expecting.
创建指向派生类对象的基类指针。这允许您创建is-a关系。派生类是基类。请参阅继承了解更多详细信息。
2<代码>。 d2=reinterpret_cast<衍生*>(b1);
您正在尝试将基类对象转换为派生类对象。但使用的强制转换操作是 .这是不正确的。
如果您计划调用基类方法,则使用基类指针。
我建议您参考FAQ Lite。
Creating Base class pointer that points to derived class object. This allows you to create is-a relationship. Class Derived is a Base. Please refer inhertance for more details.
2
. d2 = reinterpret_cast<derived*>(b1);
You are trying to convert a base class object to derived class object. But the cast operation used is . Its not correct.
If you are planning to call base class method then use Base class pointers.
I recommend you to refer FAQ Lite.
(1) 您有一个指向派生类对象的基类指针。在实现多态性时使用此方法,其中您有多个从公共基类继承的派生类。然后,您可以根据基类指针的类型调用正确的派生类函数,前提是该函数是虚拟的。
而且它不称为对象切片。对象切片是指将派生类对象分配给基类对象(而不是指针),其中派生类对象的成员被切片(保留)。因此,您无法从基类对象访问这些切片成员。
(2) 除了使用reinterpret_cast 的行之外,其他语句都可以。
(3) 如果您使用对象或重写派生类函数来调用基类版本(如其他答案中提到的),则必须使用范围解析运算符。但是,您可以使用指针:
(1) You are having a base class pointer point to a derived class object. This is used when implementing polymorphism where you have several derived classes which inherits from a common base class. You can then call the correct derived classes' function according to its type through the base class pointer, provided the function is virtual.
And it is not called object slicing. Object slicing is when you assign a derived class object to a base class object (not pointers) where in the members of the derived class object are sliced, left off. Because of this, you cannot access those sliced members from the base class object.
(2) The other statements are fine except for the line using reinterpret_cast.
(3) You'll have to use the scope resolution operator if you're using objects or override the derived class function to call the base class version (like mentioned in other answers). However, you can use pointers: