沿用上篇博客的代码,进行探究。
首先要明白:
说明1:
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
说明2:
出于效率考虑,没有必要将所有成员函数都声明为虚函数
说明3 :C++编译器,执行HowToPrint函数,不需要区分是子类对象还是父类对象
void main()
{
Child c1; //定义一个子类对象 ,在这个过程中,在父类构造函数中调用虚函数print 能发生多态吗?
//c1.print();
cout<<"hello..."<<endl;
system("pause");
return ;
}
想探究一个问题:定义一个子类对象 ,在这个过程中,在父类构造函数中调用虚函数print 能发生多态吗?答案是不能发生的,只会调用它自己的虚函数print;同样道理,如果是在子类中去调用虚函数print,也不能发生多态,而只是调用的子类中的虚函数。这涉及到的就是:vptr指针的分布初始化问题。
当执行某个对象的构造函数的时候,vptr会执行这个对象对应的虚函数列表中的函数,不会再去执行其他对象的虚函数,所以,无法实现多态。
总体代码
dm03_vptr指针的分步初始化.cpp
#include <iostream>
using namespace std;
//构造函数中调用虚函数能发生多态吗?
class Parent
{
public:
Parent(int a=0)
{
this->a = a;
print();
}
virtual void print()
{
cout<<"我是爹"<<endl;
}
private:
int a;
};
class Child : public Parent
{
public:
Child(int a = 0, int b=0):Parent(a)
{
this->b = b;
print();
}
virtual void print()
{
cout<<"我是儿子"<<endl;
}
private:
int b;
};
void HowToPlay(Parent *base)
{
base->print(); //有多态发生 //2 动手脚
}
void main()
{
Child c1; //定义一个子类对象 ,在这个过程中,在父类构造函数中调用虚函数print 能发生多态吗?
//c1.print();
cout<<"hello..."<<endl;
system("pause");
return ;
}