随笔分类 - Effective C++(二)——构造/析构/赋值运算符
摘要:设计良好的面向对象系统会将对象的内部封装起来,只留两个函数负责对象拷贝,即copy构造函数与copy assignment操作符。编译器会在必要的时候为类创建coping函数,并说明这些“编译器生成版”的行为:将被拷贝对象的所有成员变量都做一份拷贝。任何时候,只要自己实现派生类的copying函数,则必须很小心的复制其基类成分。这些成分往往是private私有的,故无法直接访问它们,因此应该让派送类的coping函数调用相应的基类函数:void logCall(const string& funcName); class Customer { public: ... Customer.
阅读全文
摘要:“自我赋值”发生在对象被赋值给自己时:class Widget{ ...};Widget w;...w = w; //赋值给自己operator=,不仅不具备“自我赋值安全性”,也不具备“异常安全性”。让operator= 具备“异常安全性”往往自动获得“自我赋值安全性”的回报。因此越来越多的人对“自我赋值”的处理态度是不去管它,而把焦点放在实现“异常安全性”上。确保代码不但“异常安全”而且“自我赋值安全”的一个替代方案是,使用所谓的copy and swap技术。此技术和“异常安全性”有密切关系,它是一个常见而够好的operator=撰写办法,其实现方式为:class Widget{pub.
阅读全文
摘要:关于赋值,可以写成连锁形式:int x, y, z;x = y = z = 15; //赋值连锁形式赋值采用右结合律,故上述赋值被解析为:x = (y = (z = 15)); 为了实现连锁赋值,赋值操作符必须返回一个reference引用指向操作符的左侧实参。下面示例是为classes实现赋值操作符时应该遵循的协议:class Widget{public: ... Widget& operator=(const Widget& rhs) //返回类型是个reference,指向当前对象 { ... return *this; //返回左侧对象 } ...};这个协议不仅适用于
阅读全文
摘要:不该在构造函数和析构函数期间调用virtual函数,这一点是C++与jave/C#不同的地方之一。假设有一个class继承体系,用来模拟股市交易如买进、卖出的订单等等。这样的交易一定要经过审计,所以每当创建一个交易对象,在审计日志中也需要创建一笔适当记录。正确的做法是在基类Transaction内将logTransaction函数改为non-virtual,然后要求派生类构造函数传递必要信息给基类Transaction的构造函数,这样那个构造函数便可安全地调用non-virtuallogTransaction。正确用法如下:class Transaction{public: Transacti
阅读全文
摘要:问题:如果一个类的析构函数必须执行一个动作,而该动作可能会在失败时抛出异常,该怎么办?举个例子,假设使用过一个class负责数据库连接:class DBConnection{public: ... static DBConnection create(); //此函数返回DBConnection对象 void close(); //关闭联机;失败则抛出异常};一个较佳策略是创建一个用来管理DBConnection资源的DBConn类,DBConn类自己提供一个close函数,因而赋予客户一个机会得益处理“因该操作而发生的异常”。DBConn也可以追踪其所管理的DBConnection是否已..
阅读全文

浙公网安备 33010602011771号