营销型网站网站,电商商城平台定制,传奇小程序代理,珠海企业网站建设制作1#xff1a;为多态基类声明virtual析构函数当我们创建一个base class指针指向新生成的derived class时#xff0c;当删除基类指针时#xff0c;如果base class是一个non-virtual析构函数时#xff0c;实际执行的结果通常是derived class中的base成分被销毁#xff0c;der…1为多态基类声明virtual析构函数当我们创建一个base class指针指向新生成的derived class时当删除基类指针时如果base class是一个non-virtual析构函数时实际执行的结果通常是derived class中的base成分被销毁derived成分没有被销毁通常解决这种问题的方法是把base class中的析构函数声明为virtual并不是只有析构函数可以声明为virtual,其他的函数也可以virtual函数的目的是为了让derived class客制化也就是实现动态联编任何class中只要带有virtual函数都需要提供一个virtual析构函数想要实现虚函数对象必须提供某些信息来决定运行期决定那个virtual函数被调用通常这个信息有vptr(virtual table pointer)来表示vptr指向一个函数指针构成的数组称为vtbl(virtual table)每一个带有virtual函数的class都有一个对应的vtbl,对象调用virtual函数的时候实际上调用的是vptr指向的vtbl;一般来说如果不想把base class用于继承一般不要定义virtual函数毕竟vptr指针会占内存的不要试图去继承一个不带虚析构函数的类这样会出问题的抽象类不能被实体化的类不能用这种类来创建对象类中带一个pure virtual析构函数通常作为base classes由于析构的顺序和初始化的顺序相反因此在声明纯虚析构函数时需要给虚析构函数提供一份定义这样编译器在derived class的析构函数创建一个对base class析构函数的调用动作即使在base class中未发生析构代码如下class AMOV{
public:virtual ~AMOV() 0;//pure virtual析构函数
};
AMOV::~AMOV() { }结论polymorphic带多态性质的base classes应该声明一个virtual析构函数如果class带有任何的virtual函数那么应该有一个virtual析构函数classes的设计目的如果不是作为base classes使用或不是为了多态性就不应该声明virtual析构函数
2别让异常逃离析构函数在两个异常同时存在的情况下程序若不结束执行就会导致不明确的行为
class dbconnection{ class dbconn{//管理对吧connection对象
public: public:static dbconnction create();//创建对象 ~dbconn() { db.close() ; }//关闭数据库连接void close();//关闭系统 private: dbconnection db;
} };问题如果close调用失败就会产生异常而析构函数中没有处理异常的机制异常在析构函数向上抛出
解决方案在析构函数中建立异常处理机制或者直接吞掉异常如果在吞掉异常后程序依旧可以可靠的运行 ~dbcnn(){try {db.close();}catch(...){//捕获异常std::abort() ;//终止程序 //方案1需要这一句 //方案2不需要}
}
另外一种比较好的方法就是重新设计dbconn接口设置一个普通函数让用户判断是否会产生异常
class dbcnn{
public:void close{db.close();closedtrue;}
~dbcnn() {
if(!closed){try{db.close();}catch(...){}}}
private:dbconnection db;bool closed;
};
3不要在构造和析构函数中调用virtual函数对于构造函数而言不能在构造过程中调用virtual函数的原因base class在构造过程中virtual函数不会下降到derived class因为在base class构造函数执行时derived class的成员还没有初始化如果此时virtual函数下降到derived class中势必会调用未初始化的变量而C不允许这一现象发生在base class构造期间virtual函数不再是virtual函数更本质的原因是在derived class对象的base class构造期间对象是base class而不是derived class不只是virtual函数会被编译器解析为base class若使用运行期类型信息如dynamic_cast和typeid,也会把对象视为base class类型因此对象在derived class构造函数开始执行前不会成为一个derived class对象对于析构函数也是同样的道理构造和析构的顺序相反一旦derived class析构函数开始执行对象内的derived class成员变量便呈现出未定义状态因为被析构了进入base class析构函数后对象变成一个base class对象为了防止传值过程中出现意外指向未初始化的成员变量可以充分利用static关键字
4令operator返回一个reference to*this为了使操作符实现连锁操作操作符必须返回一个reference指向操作符的左侧实参