在C++的期末考试中,遇到了关于用子类对象去初始化基类对象的情况,并且综合运用了
指针、引用与直接调用的方式进行相应的操作,以判断相应的输出结果。相应的代码如下:

#include<iostream>
using namespace std;
class A{
public:
int i=10;
virtual void print(){cout<<"class A="<<i<<endl;}
};

class B:public A{
public:
B(void){i=20;}
void print(){cout<<"classB"<<endl;}
};
int main()
{
B b;
A a1 = b; // 此处使用赋值的方式进行初始化。基类对象的数据将会被覆盖,但是基类的虚函数指针不变
A &a2 = b; // 以引用的方式进行基类对象的初始化
A *a3 = &b; // 以指针的方式进行基类对象的初始化
a1.print();
a2.print();
a3->print();
return 0;
}

相应的结果如下:
class A=20
class B
class B

从上述结果可以很清楚的看到,由于基函数中将void print()函数声明为了virtual函数,因此,当采用赋值的方式时,其函数部分还是virtual声明的函数部分,但是所调用的数据则是子类对象本身的。但是通过引用和指针的方式,则顺利地调用子类对象的print()函数,这种方法跟声明一个指向基类的指针,然后指向子类对象的道理其实是一样的。

有趣的是,当我去掉virtual声明后的结果就有一点不一样了:

#include<iostream>
using namespace std;
class A{
public:
int i=10;
virtual void print(){cout<<"class A="<<i<<endl;}
};

class B:public A{
public:
B(void){i=20;}
void print(){cout<<"classB"<<endl;}
};
int main()
{
B b;
A a1 = b; // 此处使用赋值的方式进行初始化。基类对象的数据将会被覆盖,但是基类的虚函数指针不变
A &a2 = b; // 以引用的方式进行基类对象的初始化
A *a3 = &b; // 以指针的方式进行基类对象的初始化
a1.print();
a2.print();
a3->print();
return 0;

相应的结果是:
classA=20
classA=20
classA=20

事实上,并不是很难理解。除去了virtual后,虽然说是在子类对象中是用同名进行覆盖了print()函数,但覆盖本身就是说有基类的内容,只是不显示而已。其相当于在子类对象将从基类继承过来的print()函数进行了基类的函数以及数据的初始化,用的还是基类自己的函数。当然,相应的数据还是被子类对象的数据进行了刷新的。