一.先看代码
class Parent
{
public:
Parent(int a) {
cout << "Parent(int )..." << endl;
this->a = a;
}
virtual void print() {
cout << "parent::print().....a="<<a << endl;
}
private:
int a;
};
class Child :public Parent
{
public:
Child(int a, int b) :Parent(a)
{
this->b = b;
}
virtual void print() {
cout << "Child::print().....b="<<b << endl;
}
private:
int b;
};
int main() {
Parent* pp = new Child(1, 2);
pp->print();
}
结果:调用了父类的构造函数,输出子类的print()函数。
二.修改代码
现在将父类中代码进行修改,增加了print()方法,那么这里调用子类print()方法,还是父类print()方法?
class Parent
{
public:
Parent(int a) {
cout << "Parent(int )..." << endl;
this->a = a;
print();这里是调用子类方法、还是父类方法?
}
virtual void print() {
cout << "parent::print().....a="<<a << endl;
}
private:
int a;
};
结果:这里的print()输出了父类中的print().
原理解释:
Parent* pp = new Child(1, 2);
在执上面代码时,会发生一些有趣的vptr指向问题。
- 首先执行new Child(1,2),进入到子类构造函数Child(int a, int b) :Parent(a)中;
- 在执行子类构造函数时,又是先执行Parent(a),进入到父类的构造函数中。这时发生下图箭头1,子类的vptr指针指向父类的虚函数表;
- 等父类构造函数结束后,又发生箭头2,vptr指针指向了子类自己的虚函数表。
代码上解释:
class Child :public Parent
{
public:
Child(int a, int b) :Parent(a)此处,调用父类构造函数,会将vptr指针当作父类处理,指向父类的虚函数表。
{
vptr指针从指向父类虚函数表,变成指向子类的虚函数表
this->b = b;
}
virtual void print() {
cout << "Child::print().....b="<<b << endl;
}
private:
int b;
};
验证:继续修改print()位置。
class Child :public Parent
{
public:
Child(int a, int b) :Parent(a)
{
this->b = b;
print();这里是调用子类方法、还是父类方法?
}
virtual void print() {
cout << "Child::print().....b="<<b << endl;
}
private:
int b;
};
结果: