@cxm-2016
2016-10-28T13:32:54.000000Z
字数 1374
阅读 2102
c++
版本:2
作者:陈小默
声明:禁止商业,禁止转载
如果我们希望同一个方法在基类和派生类中的行为是不同的的时候,我们可以采取一种比较复杂的行为——多态。具有多态性质的对象的行为取决于调用对象,即同一个方法的行为随上下文而异。为了实现多态C++提供了两种重要的机制[1]
- 在派生类中重新定义基类的方法。
- 使用虚方法
无论我们是否使用多态,都可以在派生类中新增成员
当派生类重写了基类的方式时,该方法就已经具有了不同的行为,当我们使用派生类对象的引用去调用重写后的方法时,就可以看到与父类不同的行为了。但是我们需要注意的一点时,如果我们要在重写的方法中使用父类的同名方法,则必须要使用函数限定名指定方法所在。不然像下面这种情况就会导致StackOverFlow
void Dog::bark(){
bark();//correct is Animals::bark();
}
加入我们需要在某些函数上使用多态性质,则需要在基类和派生类的相应方法上声明virtual关键字。假如我们没有声明virtual关键字,则方法的行为与引用类型相关,而与具体的对象无关。也就是说在没有声明virtual的情况下,基类指针一定会调用基类定义的方法,尽管基类指针可能会指向派生类对象。而定义了virtual关键字后,函数的调用就与指针类型无关,而是与对象相关,就算当前指针是基类类型,也会调用对象重写过的方法。
不添加virtual的示例
class Base{
public:
show(){cout<<"base"<<endl;};
...
}
class Imp : Base{
public:
show(){cout<<"Imp"<<endl;};
...
}
...
int main(){
Base base = Imp();
base.show();
}
输出结果
base
添加virtual的示例
class Base{
public:
virtual show(){cout<<"base"<<endl;};
...
};
class Imp : Base{
public:
virtual show(){cout<<"Imp"<<endl;};
...
};
...
int main(){
Base base = Imp();
base.show();
}
输出结果
Imp
class Base{
public:
virtual ~Base();
};
基类对象声明虚拟的析构函数是为了保证释放派生对象时能够按照正确的顺序调用析构函数。
当我们使用多态性质的时候,大部分都会使用基类指针指向派生类对象。所以原因跟使用虚方法的原因类似。当我们没有声明虚析构函数的时候,delete时只会调用位于指针类型的析构函数。如果我们声明了虚的析构函数,则会调用相应对象类型的虚构函数,而后自动调用基类的析构函数。因此在基类声明虚拟析构函数可以保证析构函数的正确调用顺序。