我已经使用虚拟打印功能声明了一个Super Class,而Child类继承了Super类。我创建了一个Child Class实例,并以两种不同的方式分配给Super Class。
#include <iostream>
using namespace std;
class Super
{
public:
Super(){}
virtual void print()
{
cout << "Super class is printing " << endl;
}
};
class Child: public Super
{
public:
Child(){}
void print()
{
cout << "Child class printing" << endl;
}
};
int main()
{
Child c;
Super s = c;
Super &ss = c;
s.print(); //prints "Super Class is printing
ss.print(); //prints "Child Class is printing
return 0;
}
为什么我们从这两个打印调用中得不到相同的输出?添加引用如何改变行为?
答案 0 :(得分:2)
s
的动态和静态类型为Super
,但c
的分配会从Super
内部创建c
子对象的副本{1}}和s
始终表现为Super
。
但是,ss
的静态类型为Super
,但其动态类型取决于其初始化,在本例中为Child
,因此虚拟调度的行为相应。
这种现象称为"object slicing"
答案 1 :(得分:1)
如果您使用超类并为其分配子类的值,则只会复制属于超类的成员(默认赋值运算符行为)。
请考虑以下事项:
#include <iostream>
using namespace std;
class Super {
public:
int a;
Super(): a(0) { }
Super(int _a): a(_a) { }
virtual void dump() {
cout << "A is : " << a << std::endl;
}
};
class Child: public Super {
public:
int b;
Child(int _a, int _b): b(_b), Super(_a) { }
virtual void dump() {
Super::dump();
cout << "B is : " << b << std::endl;
}
};
int main() {
Child c(5, 10);
Super s;
s.dump(); // A is 0
s = c;
s.dump(); // A is 5 (but there is no B in s
// so calling Child::dump would be nonsensical
}
因此,当您将子值分配给父级时,您可以看到调用子级dump
是没有意义的;因为父上下文中没有“b”。
请注意以下声明: c = s;
是非语义的,因为虽然parentage是确定性的(Child是Super的类型,因此隐式运算符Super& Super::operator=(const Super&)
适用于派生的Child
类,反之则不正确;即{{1}在Child& Child::operator=(const Child&)
好的,因为理解引用变量是什么造成的混乱。引用变量是初始化的任何内容的同义词。您可以使用与原始参数完全相同的参考变量。
在你的情况下:
Super
与
相同 ss.print();
” 要更明确地看到这一点,请考虑以下代码段:
c.print();