目录
一.基类的constructor和destructor内
二.使用的是基类的对象而不是基类对象的pointer或reference
存在两种情况,虚函数机制不会出现预期行为:
即不根据虚函数的机制来调用类中对应的虚函数
示例中使用的基类和派生类:
class base_class
{
private:
string base_logo;
public:
virtual void print()const
{
cout << "base_class" << endl;
}
base_class(string logo)
{
base_logo = logo;
print();
}
~base_class()
{
print();
}
};
class derived_class:base_class
{
private:
string derived_logo;
public:
virtual void print()const
{
cout << "derived_logo" << endl;
}
derived_class(string logo)
{
derived_logo = logo;
print();
}
~derived_class()
{
print();
}
};
示例中使用的函数:
void print(base_class d1, base_class* d2, base_class& d3) //基类引用和指针为参数类型时,可以传递基类或派生类作为参数
{
d1.print();
d2->print();
d3.print();
}
一.基类的constructor和destructor内
1.原理:在构造派生类对象时,基类的构造函数先被调用,且此时派生类中的data member尚未初始化,若此时基类构造函数调用派生类的那一份虚函数,则可能访问未经初始化的data member,因此在构造函数中只会调用该类本身的虚函数。(对于析构函数destructor原理一致)
2.演示示例:
int main()
{
//基类对象
base_class b1("base");
b1.~base_class();
//派生类对象
derived_class d1("derived");
d1.~derived_class();
system("pause");
return 0;
}
如运行结果所示:基类,派生类各自的构造函数和析构函数中调用的虚函数均是自己类中的虚函数。
二.使用的是基类的对象而不是基类对象的pointer或reference
1.原理:当我们为基类声明了一个实际对象,同时也就分配出了足够容纳该实际对象的内存空间,如果稍后传入的是派生类对象,则没有足够的内容放置派生类中的各个data member。(因此,若将派生类参数传给基类参数类型,则会将派生类多出的部分切除)
2.演示示例:
int main()
{
//基类对象
base_class b1("base");
//派生类对象
derived_class d1("derived");
print(d1, &d1, d1);
system("pause");
return 0;
}
函数的第一个参数是一个实际对象,而第二个第三个参数分别是指针和引用。
如运行结果所示:第一个参数对象调用的print()中调用的虚函数为基类的虚函数,第二个第三个参数对象调用的print()中调用的虚函数为派生类的虚函数。(因此将类对象作为参数传递时,最好均以指针或是引用的方式进行传递)