标签:c++ effective c++ 构造析构函数 虚函数
每一个类中都有构造函数、析构函数、赋值操作符。这几个函数是一个类最根本的函数,它控制着创建对象并初始化、对象消亡时的清理以及摆脱旧值赋新值。这样函数如果有问题,那么影响极为严重。
class Empty{ };经过编译器处理后会有默认构造函数、复制构造函数、赋值操作符和析构函数。这些函数都是public且inline。
class Empty{ public: Empty(){} Empty(const Empty& rhs){} Empty& operator=(const Empty& rhs){} ~Empty(){} };
template<typename T> class NamedObject{ public: NamedObject(const char* name, const T& value); NamedObject(const std::string& name, const T& value); private: std::string& nameValue; const T objectValue; };两个成员变量,一个是引用:初始化后不能更改,一个是常量:也是初始化后不能更改。
class HomeForSale { …… };天下没有两个一模一样的房子,因此复制构造函数和赋值操作符不应该使用。
HomeForSale h1; HomeForSale h2; HomeForSale h3(h1);//应该出错 h1=h2;//应该出错但是编译器默认帮我们合成了这两个函数。而且编译器合成的函数都访问都是public。
class HomeForSale { public: …… private: HomeForSale(const HomeForSale&); HomeForSale& operator=(const HomeForSale&); };只声明,不实现。如果普通的调用会在编译阶段出现错误(无法访问private),但是友元和member函数却可以访问,这样的话错误会发生的链接阶段,因为我们只是声明,没有实现。
class Uncopyable{ { protected: Uncopyable(){} ~Uncopyable(){}; private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); };让其他类来继承此类即可
class HomeForSale:public Uncopyable { …… };这样一来,在HomeForSale类中如果生产对应的赋值或复制构造函数,会调用基类对应的函数,其基类对应函数为private,会出现编译错误。
class SpecialString:public std::string{ …… };这时如果通过基类指针使用,在delete时,可能会造成内存泄漏。要记住,STL中的容器都没有虚的析构函数。
class AWOV { public: virtual ~AWOV()=0; };如果把它当作基类,会有问题,因为其析构函数只有声明。析构函数的调用时从派生类到基类,如果没定义,会发生链接错误,这是要定义个空的析构函数
AWOV::~AWOV(){}
class Widget{ public: …… ~Widget(){……} }; void doSomething() { std::vector<Widget> v; …… //v要析构,会调用Widget的析构函数 }
class DBConnection { public: …… void close();//关闭数据库 };为了确保用户在使用后关闭连接,在析构函数中关闭连接。
class DBConnection { public: …… ~DBConn()//析构函数关闭连接 { db.close(); } private: DBConnection db; };
~DBConn()//析构函数关闭连接 { try{ db.close(); } catch(……) { //记录下对close调用的失败 std::abort();//退出 } }2、吞下这个异常。
~DBConn()//析构函数关闭连接 { try{ db.close(); } catch(……) { //记录下对close调用的失败 } }吞下这个异常也不是个好主意,它压制了某些失败动作的重要信息。
class Transaction{ public: Transaction(); virtual void logTransaction()const//virtual function { //log the Transaction std::cout<<"This is Transaction logTransaction"<<std::endl; } }; Transaction::Transaction() { logTransaction();//called in Ctor }在买进和卖出的类中,可以重写logTransaction()函数。
class BuyTransaction:public Transaction{ public: virtual void logTransaction()const { std::cout<<"This is BuyTransaction logTransaction"<<std::endl; } }; class SellTransaction:public Transaction{ public: virtual void logTransaction()const { std::cout<<"This is SellTransaction logTransaction"<<std::endl; } };
BuyTransaction b;
class Transaction{ public: Transaction(); void Init() { logTransaction(); } virtual void logTransaction()const//virtual function { //log the Transaction std::cout<<"This is Transaction logTransaction"<<std::endl; } }; Transaction::Transaction() { Init(); }就没那么容易看出问题了。构造函数调用了Init()函数,在Init()函数中调用了virtual函数。
#include<iostream> class Transaction{ public: explicit Transaction(const std::string& parameter); void logTransaction(const std::string& parameter)const//virtual function { //log the Transaction std::cout<<"This is "<<parameter<<" logTransaction"<<std::endl; } }; Transaction::Transaction(const std::string& parameter) { logTransaction(parameter);//called in Ctor } class BuyTransaction:public Transaction{ public: BuyTransaction() :Transaction(CreatPamameter()) { } private: static std::string CreatPamameter() { return "BuyTransaction"; } }; class SellTransaction:public Transaction{ public: SellTransaction() :Transaction(CreatPamameter()) { } private: static std::string CreatPamameter() { return "SellTransaction"; } }; int main() { BuyTransaction b; SellTransaction s; return 0; }这样就解决了开始提出的问题。在derived类中使用了private static函数来创建参数。这样增强了代码的可读性,另外static函数不会指向未初始化的derived类中的变量。
《Effective C++》构造/析构/赋值 函数:条款5-条款9
标签:c++ effective c++ 构造析构函数 虚函数
原文地址:http://blog.csdn.net/kangroger/article/details/41986049