C++中虚函数与函数

析构函数为什么要声明为虚 函数???

基类的析构函数需要声明为虚函数: 
当派生类对象经由一个基类指针被删除,而该基类带着一个non-virtual析构函数,实际执行时通常发生的是对象的派生类成员没有被销毁。这也就是局部销毁,会发生内存泄漏,所以我们通常将基类的析构函数需要声明为虚函数。

class Base
{
public:
    Base()
       :_b(1)
   {
       cout << "Base()" << endl;
   }
   ~Base()
   {
       cout << "~Base()" << endl;
   }
protected:
   int _b;
};
class Derived : public Base
{
public:
   Derived()
       :_d(2)
   {
       cout << "Derived()" << endl;
   }
   ~Derived()
   {
       cout << "~Derivde()" << endl;
   }
protected:
   int _d;
};
void test()
{
   Base *p;
   p = new Derived;
   delete p;
}

运行结果:

可以发现程序只删除了base class对象,造成了局部销毁。
解决:将基类的析构函数生命为virtual,此后删除派生类对象就会销毁整个对象,包括派生类成分。

class Base
{
public:
    Base()
       :_b(1)
   {
       cout << "Base()" << endl;
   }
   virtual ~Base()
   {
       cout << "~Base()" << endl;
   }
protected:
   int _b;
};
class Derived : public Base
{
public:
   Derived()
       :_d(2)
   {
       cout << "Derived()" << endl;
   }
   ~Derived()
   {
       cout << "~Derivde()" << endl;
   }
protected:
   int _d;
};
void test()
{
   Base *p;
   p = new Derived;
   delete p;
}

运行结果:

可以发现,如果将base class的析构函数声明为虚函数,就不存在局部销毁的问题。

注意:

1.任何类只要带有 virtual 函数都几乎应该也有一个 virtual 析构函数。 

2.如果类不含 virtual 函数,通常表示他并不意图被用做一个基类。当类不企图被当作基类时候令其析构函数为virtual 往往是个馊主意,这个原因大家也可以想一下。

不能被声明为虚函数的函数

1.普通函数

普通函数只能被重载,不能被重写,声明为虚函数没有任何意义,因为编译器会在编译时绑定函数。

2.构造函数: 
因为构造函数本身就是为了明确初始化对象成员才产生的。如果构造函数是虚函数,就需要通过 vtable 来调用,但是此时对象还没有实例化,无法找到 vtable ,所以不能为虚函数。 
从实现上来看,vtable 是在构造函数调用之后才建立的,因而构造函数不能为虚函数,同时编译器也根本无法通过编译。

3.内联成员函数: 
因为内联函数是为了在代码中直接展开,减少函数调用的花费,而虚函数是为了在继承后对象能够准确的执行自己的动作。 
而且内联函数在编译时被展开,虚函数在运行时才能动态绑定

4.静态成员函数: 
静态成员函数对于每一个类来说只有一份,所有的对象公用一份代码,它的实现就不是为了构成多态,也没有要动态绑定的必要性。

5.友元函数: 
因为友元函数并不支持继承,对于没有继承特性的函数没有虚函数的说法。

猜你喜欢

转载自blog.csdn.net/sing_Hwang/article/details/84193657