virtual member function
在基类中声明一个成员函数为virtual是为了说明该函数能在派生类中被override;派生类一般会重定义所继承的virtual function,如果派生类没有重定义某个virtual function,则使用基类中定义的版本。
除了构造函数之外,任意非static成员函数都可以是虚函数。保留字只在类内部的成员函数声明中出现,不能用在类定义体外部出现的函数定义上。
一旦函数在基类中声明为虚函数,它就一直为虚函数,派生类无法改变该函数为虚函数这一事实。派生类重定义虚函数时,可以使用virtual保留字,但不是必须这样做。
通过引用或指针调用virtual function时,编译器将生成代码,在运行时确定调用哪个函数,被调用的是与动态类型相对应的函数,即如果对象是基类则调用基类的virtual function,如果是派生类则调用派生类的virtual function。如果调用nonvirtual function,则无论实际对象是什么类型,都执行基类类型所定义的函数。
派生类中虚函数的声明必须与基类中的定义方式完全匹配,但有一个例外:返回对基类型的引用(或指针)的虚函数。派生类中的虚函数可以返回基类函数所返回类型的派生类的引用(或指针)。例如,Item_base 类可以定义返回 Item_base 的虚函数,如果这样,Bulk_item 类中定义的实例可以定义为返回 Item_base 或 Bulk_item*。
虚析构函数
派生类析构函数不负责撤销基类对象的成员,编译器总是显式调用派生类对象基类部分的析构函数;对象的撤销顺序与构造顺序相反:首先运行派生析构函数,然后按继承层次依次向上调用各基类析构函数。
class Derived: public Base {public: //Base::~Base invoked automatically ~Derived() { /* do what it takes to clean up derived members */ }};
如果删除基类指针,则需要运行基类析构函数并清除基类的成员,如果对象实际是派生类型的,则没有定义该行为。要保证运行适当的析构函数,基类中的析构函数必须为虚函数:
derived_destructor
1 #include <iostream> 2 using namespace std; 3 4 class A { 5 public: 6 ~A() { 7 cout << "~A() is called" << endl; 8 } 9 };10 11 class B : public A {12 public:13 ~B() {14 cout << "~B() is called" << endl;15 }16 };17 18 void destory(A *ptr) {19 if ( ptr )20 delete ptr;21 }22 23 int main() {24 A *a = new A;25 B *b = new B;26 destory(a);27 destory(b);28 29 return 0;30 }
运行输出为:
~A() is called
~A() is called
从输出结果可以看出由于析构函数不是虚函数通过基类对象指针并不能调用实际对象的析构函数,要实现运行时多态只要将A的析构函数声明为虚函数即可:virtual ~A(),修改后的运行输出为:
~A() is called
~B() is called
~A() is called
像其他虚函数一样,析构函数的虚函数性质都将继承。因此,如果层次中根类的析构函数为虚函数,则派生类析构函数也将是虚函数,无论派生类显式定义析构函数还是使用合成析构函数,派生类析构函数都是虚函数。
原文链接: https://www.cnblogs.com/edwardlost/archive/2010/11/14/1875513.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/17374
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!