多态基类的析构函数必须加上virtual
2014-03-19 17:13
323 查看
《Effective C++》说:
因为C++明确指出,当derived class对象经由一个base class指针被删除,而base class带着一个non-virtual析构函数,其结果未有定义---实际执行时通常发生的是对象的derived成分没被销毁。如:baseclass *ptb = derivedclassFuc() //子类的一个函数; 其中baseclass中有个non-virtual析构函数。解决这一问题的方法就是把基类中的析构函数声明为virtual,通常还有其他virtual函数。任何class只要还有virtual函数都几乎确定应该也有一个virtual析构函数。
如果class不含virtual函数,通常表示它并不意图被用做一个base class.当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。许多人的心得是:只有当class内含至少一个virtual函数,才为它声明virtual析构函数。
有时候令Class带一个pure virtual析构函数,可能颇为便利,纯虚函数导致抽象类,也就是不能被实体化的类,你不能为这种类型创建对象。所以为你希望它成为抽象的那个类声明一个pure virtual析构函数,这样你就不需要担心析构函数的问题了,不过你必须为这个pure virtual析构函数提供一份定义:如,AWOV::~AWOV ( ) { …….},析构函数的运作方式是,最深层派生的那个class其析构函数最先被调用,然后是其每一个base class的析构函数被调用。编译器会在AWOV的derived
classes的析构函数中创建一个对~AWOV的调用动作,所以你必须为这个函数提供一份定义,否则,连接器会出问题。
=======================================
把析构函数定义成虚函数,可以有效的防止在之后继承的时候,子类指针的内存泄露.
比如,
class A
class B:public A
A *ptr=new B
在这种情况下调用析构函数的时候,就会发生删除了A的空间而没有删除B的空间,
所以将基类定义为抽象类,可以让其子类动态的去调用它自身的函数。
========================================
class Base
{
public:
Base(){}
virtual void VirFun()
{
}
~Base(){} //实际上这里必须加virtual
private:
//Some attribute
};
class Sub : public Base
{
public:
Sub(){}
virtual void VirFun()
{
}
~Sub(){}
private:
//Some attribute
};
上面的例子是个简单的多态。
在我们应用的时候,我们经常会这么干:
Base * pBase = new Sub();//new了一个Sub对象,它实际上包含了Base 的子对象。
pBase->VirFun(); //很好,它会根据实际的类型调用Sub 的 VirFun()
delete pBase;//完蛋了,它调用了Base的析构。Sub的析构?这可不关我事,我可是Base类型的。
于是内存泄漏了。。。
给Base的析构函数加上virtual之后呢?
delete pBase; //很好,它继续多态调用实际类型对象的析构。
大家知道,子类的析构函数会自动调用父类的析构。
于是,啊哈,终于安全了。
至此,大家应该对题目的意思有了大概的了解了。
有没有发现,virtual 析构函数挺有意思的,它的子类析构函数名字和父类不同,一样会重写父类的析构函数。
为什么题目要强调“多态 基类”呢?
class Base
{
public:
Base(){}
void Fun()
{
}
virtual ~Base(){}
private:
//Some attribute
};
class Sub : public Base
{
public:
Sub(){}
void Fun()
{
}
~Sub(){}
private:
//Some attribute
};
这样的继承中,有没有必要给父类析构函数加virtual呢?
从语法意义上来说,是应该的,因为你像下面这样写的时候,语法是没有错误的:
Base * pBase = new Sub();//new了一个Sub对象,它实际上包含了Base 的子对象。
delete pBase; //很好啊,程序多安全啊。有什么问题吗?
在这样写的时候,你应该谴责自己。
pBase的所有行为都是Base中定义的,为什么要给它一个Sub的身体呢?
(为什么网上很多男士都爱用美女作头像呢。。。)
所以,当你设计的类系不具备多态性的时候,请不要:
1.用父类的指针指向子类;
2.给父类的析构函数加上virtual(毕竟虚函数表也是不小的开销不是?)
因为C++明确指出,当derived class对象经由一个base class指针被删除,而base class带着一个non-virtual析构函数,其结果未有定义---实际执行时通常发生的是对象的derived成分没被销毁。如:baseclass *ptb = derivedclassFuc() //子类的一个函数; 其中baseclass中有个non-virtual析构函数。解决这一问题的方法就是把基类中的析构函数声明为virtual,通常还有其他virtual函数。任何class只要还有virtual函数都几乎确定应该也有一个virtual析构函数。
如果class不含virtual函数,通常表示它并不意图被用做一个base class.当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。许多人的心得是:只有当class内含至少一个virtual函数,才为它声明virtual析构函数。
有时候令Class带一个pure virtual析构函数,可能颇为便利,纯虚函数导致抽象类,也就是不能被实体化的类,你不能为这种类型创建对象。所以为你希望它成为抽象的那个类声明一个pure virtual析构函数,这样你就不需要担心析构函数的问题了,不过你必须为这个pure virtual析构函数提供一份定义:如,AWOV::~AWOV ( ) { …….},析构函数的运作方式是,最深层派生的那个class其析构函数最先被调用,然后是其每一个base class的析构函数被调用。编译器会在AWOV的derived
classes的析构函数中创建一个对~AWOV的调用动作,所以你必须为这个函数提供一份定义,否则,连接器会出问题。
=======================================
把析构函数定义成虚函数,可以有效的防止在之后继承的时候,子类指针的内存泄露.
比如,
class A
class B:public A
A *ptr=new B
在这种情况下调用析构函数的时候,就会发生删除了A的空间而没有删除B的空间,
所以将基类定义为抽象类,可以让其子类动态的去调用它自身的函数。
========================================
class Base
{
public:
Base(){}
virtual void VirFun()
{
}
~Base(){} //实际上这里必须加virtual
private:
//Some attribute
};
class Sub : public Base
{
public:
Sub(){}
virtual void VirFun()
{
}
~Sub(){}
private:
//Some attribute
};
上面的例子是个简单的多态。
在我们应用的时候,我们经常会这么干:
Base * pBase = new Sub();//new了一个Sub对象,它实际上包含了Base 的子对象。
pBase->VirFun(); //很好,它会根据实际的类型调用Sub 的 VirFun()
delete pBase;//完蛋了,它调用了Base的析构。Sub的析构?这可不关我事,我可是Base类型的。
于是内存泄漏了。。。
给Base的析构函数加上virtual之后呢?
delete pBase; //很好,它继续多态调用实际类型对象的析构。
大家知道,子类的析构函数会自动调用父类的析构。
于是,啊哈,终于安全了。
至此,大家应该对题目的意思有了大概的了解了。
有没有发现,virtual 析构函数挺有意思的,它的子类析构函数名字和父类不同,一样会重写父类的析构函数。
为什么题目要强调“多态 基类”呢?
class Base
{
public:
Base(){}
void Fun()
{
}
virtual ~Base(){}
private:
//Some attribute
};
class Sub : public Base
{
public:
Sub(){}
void Fun()
{
}
~Sub(){}
private:
//Some attribute
};
这样的继承中,有没有必要给父类析构函数加virtual呢?
从语法意义上来说,是应该的,因为你像下面这样写的时候,语法是没有错误的:
Base * pBase = new Sub();//new了一个Sub对象,它实际上包含了Base 的子对象。
delete pBase; //很好啊,程序多安全啊。有什么问题吗?
在这样写的时候,你应该谴责自己。
pBase的所有行为都是Base中定义的,为什么要给它一个Sub的身体呢?
(为什么网上很多男士都爱用美女作头像呢。。。)
所以,当你设计的类系不具备多态性的时候,请不要:
1.用父类的指针指向子类;
2.给父类的析构函数加上virtual(毕竟虚函数表也是不小的开销不是?)
相关文章推荐
- 必须为多态基类声明 virtual 析构函数
- 多态基类的析构函数请加上virtual
- 关于多态基类的析构函数声明为virtual
- effect C++ 为多态基类声明virtual 析构函数
- 当使用多态时,请为基类声明 virtual 析构函数
- c++之Item7在多态基类中将析构函数声明为virtual
- 多态时最好将基类的析构函数设为virtual
- [翻译] Effective C++, 3rd Edition, Item 7: 在 polymorphic base classes(多态基类)中将 destructors(析构函数)声明为 virtual(虚拟)
- Effective C++ 条款07 为多态基类声明virtual 析构函数
- Effective C++ 条款07 为多态基类声明virtual 析构函数
- C++类继承--基类析构函数加上Virtual
- C++将多态基类的析构函数声明为virtual的作用
- 继承基类析构函数一定要加上virtual
- 多态时最好将基类的析构函数设为virtual、 C++中两个类相互包含引用问题 (转载)
- Effective C++笔记之四 多态基类申明为virtual 析构函数
- 条款07:为多态基类声明virtual析构函数(Declare destructors virtual in polymorphic base classes.)
- [转]c++ 为什么要将基类的析构函数声明为Virtual?
- C++中基类的析构函数为什么要用virtual虚析构函数
- polymorphic base classes(多态基类)中将 destructors声明为 virtual
- Q_PROPERTY 的属性名称 必须是确定的,如果需要多态,属性名称写基类的