C++ 的行为对象参考
考虑以下代码段:
class Window // Base class for C++ virtual function example
{
public:
virtual void Create() // virtual function for C++ virtual function example
{
cout <<"Base class Window"<<endl;
}
};
class CommandButton : public Window
{
public:
void Create()
{
cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl;
}
};
int main()
{
Window *button = new CommandButton;
Window& aRef = *button;
aRef.Create(); // Output: Derived class Command Button - Overridden C++ virtual function
Window bRef=*button;
bRef.Create(); // Output: Base class Window
return 0;
}
aRef和bRef都被分配了*button,但是为什么两个输出不同。 分配给引用类型和非引用类型有什么区别?
Consider the following code segment:
class Window // Base class for C++ virtual function example
{
public:
virtual void Create() // virtual function for C++ virtual function example
{
cout <<"Base class Window"<<endl;
}
};
class CommandButton : public Window
{
public:
void Create()
{
cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl;
}
};
int main()
{
Window *button = new CommandButton;
Window& aRef = *button;
aRef.Create(); // Output: Derived class Command Button - Overridden C++ virtual function
Window bRef=*button;
bRef.Create(); // Output: Base class Window
return 0;
}
Both aRef and bRef get assigned *button, but why are the two output different.
What is the difference between assigning to Reference type and non Reference type?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您遇到了切片问题。
这里bRef不是引用而是对象。当您将派生类型分配给 bRef 时,您将切掉派生部分,只留下一个由 CommandButton 构造的 Window 对象。
所发生的情况是,bRef 是在上面的语句中使用编译器为 Window 类生成的复制构造函数创建的。这个构造函数所做的就是将成员元素从 RHS 复制到新构造的对象。由于该类不包含任何成员,所以什么也没有发生。
旁注:具有虚拟成员的类也应该有一个虚拟析构函数。
You have encountered the slicing problem.
Here bRef is not a reference but an object. When you assign a derived type onto bRef you are slicing the derived part off leaving you with just a Window object constructed form a CommandButton.
What is happening is that bRef is created in the above statement using the compiler generated copy constructor for the class Window. All this constructor does is copy member elements from the RHS to the newly constructed object. Since the class contains no members nothing is happening.
On a side note: A class with virtual members should also have a virtual destructor.
aRef
具有Window
static 类型,但CommandButton
dynamic 类型bRef 只是一个
Window
类型的对象(CommandButton
'part' 在副本中丢失了)通常称为对象切片,通常通过使基类抽象(通过提供纯虚函数)或不可复制(例如使用 boost::noncopyable),因为任何一种解决方案都会使代码无法在线编译 Window& 。 aRef = *按钮;。
现在,为什么
bRef.Create()
调用Window::Create
?好吧,bRef
中除了一个Window
之外什么也没有,所以确实没有太多的选择。这本质上就像声明一个Window
并在其上调用Create
:事实上bRef
是从CommandButton
复制的实例不相关,因为CommandButton
部分在副本中丢失。我将尝试通过引用标准 (10.3/6) 来使这一点更清楚:
只有通过指针或间接引用,对象的静态类型才能与其动态类型不同。
aRef
hasWindow
static type butCommandButton
dynamic typebRef
is simply an object of typeWindow
(theCommandButton
'part' was lost in the copy)This is commonly known as object slicing and it usually prevented by making base classes either abstract (by providing a pure virtual function) or non copyable (for example using
boost::noncopyable
), because either solution would make the code fail to compile on lineWindow& aRef = *button;
.Now, why does
bRef.Create()
callWindow::Create
? Well, there is nothing more than aWindow
inbRef
so there really isn't much of an alternative. This is essentially like declaring aWindow
and callingCreate
on it : the fact thatbRef
was copied from aCommandButton
instance is irrelevant because theCommandButton
portion was lost in the copy.I'll try to make this clearer by quoting the standard (10.3/6) :
Only through a pointer or reference indirection can the static type of an object differ from its dynamic type.
bRef
的静态和动态类型仅限于Window
。虚拟机制仅适用于引用和指针。bRef
是一个对象,而不是引用或指针。The static as well as dynamic type of
bRef
isWindow
only. Virtual mechanism works only with references and pointers.bRef
is an object not a reference or a pointer.这里的
bRef
不是对button
的引用(您只是这样命名的)。 bRef 仅获取基本子对象,即Window
。Here
bRef
is not the reference tobutton
(you just named it so). bRef gets only the base subobject which isWindow
.