Effective C++改善程序与设计的55个具体做法2 构造/析构/赋值运算
条款05: Kown what functions C++ silently writes and calls.
class Empty {
}; 等价于如下的类
class Empty{
publicEmpty(){};Empty(const Empty& rhs){}~Empty(){} Empty operation = (const Empty& rhs) {}
};下面代码造成上述每一个函数被编译器产出:
Empty e1; // default构造函数// 析构函数
Empty e2(e1); // copy构造函数
e2 = e1; // copy assignment操作符 区分一下拷贝构造与拷贝赋值:
#include
using namespace std;class CompareCopyAssignAndCopyCtr{
public:CompareCopyAssignAndCopyCtr(){cout << "CompareCopyAssignAndCopyCtr"<< endl;}; ~CompareCopyAssignAndCopyCtr(){cout << "~CompareCopyAssignAndCopyCtr"<< endl;}; CompareCopyAssignAndCopyCtr(const CompareCopyAssignAndCopyCtr&){cout << "Copyctr"<< endl;};CompareCopyAssignAndCopyCtr& operator=(const CompareCopyAssignAndCopyCtr&){cout << "Copyassign"<< endl;return *this;};
}; int main(int argc, char** argv) {CompareCopyAssignAndCopyCtr c1;CompareCopyAssignAndCopyCtr c2;cout << "---------------------"<< endl;CompareCopyAssignAndCopyCtr c3(c2); //copy ctr cout << "---------------------"<< endl;c2 = c1; //copy assigncout << "---------------------"<< endl;CompareCopyAssignAndCopyCtr c4 = c1; //copy ctr cout << "---------------------"<< endl;return 0;
}
运行结果如下:
#include
using namespace std;template
class NamedObject{
public:NamedObject(const string& name, const T& value);void printInfo();
private:string nameValue;T objectValue;
};template
NamedObject::NamedObject(const string& name, const T& value){nameValue = name;objectValue = value;
};template
void NamedObject::printInfo(){cout << "NamedObject's Name is " << nameValue << endl;
};int main(int argc, char** argv) {string newDog("Lucky"); string oldDog("Hasq");NamedObject p(newDog, 2);NamedObject s(oldDog, 36);p.printInfo();s.printInfo();p = s;p.printInfo();s.printInfo(); return 0;
} 运行结果如下:
int main(int argc, char** argv) {NamedObject m;return 0;
} 编译报错:
[Error] no matching function for call to 'NamedObject由于其中声明了一个构造函数,编译器于是不再为它创建default构造函数。为了说明这一点,再举一个例子
using namespace std;class Fruit {
public:Fruit(int id);string s;
};Fruit::Fruit(int id){
};class Apple: public Fruit {
public:Apple();
};Apple::Apple(){
};int main () {Apple apple;
} 编译报错: [Error] no matching function for call to 'Fruit::Fruit()'
#include
using namespace std;
template
class NamedObject{
public:NamedObject(string& name, const T& value);void printInfo();
private:string& nameValue;const T objectValue;
};template
NamedObject::NamedObject(string& name, const T& value): nameValue(name), objectValue(value) {
}template
void NamedObject::printInfo(){cout << "NamedObject's Name is " << nameValue << endl;
};int main(int argc, char** argv) {string newDog("Lucky");string oldDog("Hasq");NamedObject p(newDog, 2);NamedObject s(oldDog, 36);p.printInfo();s.printInfo();p = s;p.printInfo();s.printInfo(); return 0;
} 编译报错: [Error] non-static reference member 'std::string& NamedObject
条款06: Explicitly disallow the use of complier-generated functions you do not want.
class HomeForSale{
};int main(int argc, char** argv) {HomeForSale h1;HomeForSale h2;HomeForSale h3(h1); //企图拷贝h1 --期望不该通过编译 h1 = h2; //企图拷贝h2 --期望不该通过编译 return 0;
}为实现阻止拷贝的作用,可将相应的成员函数声明为private并且不予实现。
class Uncopyable{
protected:Uncopyable(); //允许derived对象构造和析构 ~Uncopyable();
private:Uncopyable(const Uncopyable&);Uncopyable& operator=(const Uncopyable&);
}; Uncopyable::Uncopyable(){
};Uncopyable::~Uncopyable(){
};class Child: public Uncopyable{
}; int main(int argc, char** argv) {Child child1;Child child2;Child child3(child2);child2 = child1;return 0;
}
此时编译报错:
[Error] 'Uncopyable::Uncopyable(const Uncopyable&)' is private
[Error] 'Uncopyable& Uncopyable::operator=(const Uncopyable&)' is private
条款07: Declare destructors virtual in polymorphic base classes
#include
using namespace std;class TimeKeeper{
public:TimeKeeper(){cout << "TimeKeeper" << endl; };~TimeKeeper(){cout << "~TimeKeeper" << endl; };
};class AtomicClock: public TimeKeeper{
public:AtomicClock(){cout << "AtomicClock" << endl; };~AtomicClock(){cout << "~AtomicClock" << endl; };
}; class WaterClock: public TimeKeeper{
}; class WristWatch: public TimeKeeper{
}; TimeKeeper* getTimeKeeper(int type){TimeKeeper* temp = NULL;switch(type){case 1:temp = new AtomicClock();break;case 2:temp = new WaterClock();break;case 3:temp = new WristWatch();break;default:break;}return temp;
}; int main(int argc, char** argv) {TimeKeeper* ptk = getTimeKeeper(1);delete ptk;return 0;
}
运行结果如下:
补充:构造和析构函数链
int main(int argc, char** argv) {AtomicClock ac;return 0;
}运行结果如下:
结论:
当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,实际执行时通常发生的是对象的derived成分没有被销毁。
改进做法,将析构函数声明为virtual函数即可,如下所示。
class TimeKeeper{
public:...virtual ~TimeKeeper(){cout << "~TimeKeeper" << endl; };
};运行结果如下:
注意:
①带有多态(polymorphic)性质的base classes应该声明一个virtual析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数(???)。
②classes的设计目的如果不是作为base classes使用,或不是为了具备多态性(polymorphically),就不该声明virtual析构函数
条款 08:Prevent exceptions from leaving destructos
#include
using namespace std;class DBConnection{
public:static DBConnection create(){DBConnection dbc;cout << "Connection Success!" << endl; return dbc; };void close(){cout << "Connection Close!" << endl; };
}; class DBConn{
public:DBConn(){ db = DBConnection::create(); } void close(){ //供客户使用的新函数 db.close();closed = true;};~DBConn(){if (!closed) {try {db.close(); //关闭连接(如果客户没有显示调用close()函数的话) }catch(...){ //如果关闭动作失败,记录下来并结束程序或吞下异常 //制作运转记录,记下对close的调用失败 }}};
private:DBConnection db;bool closed;
}; int main(int argc, char** argv) {DBConn dbconn;return 0;
}运行结果如下:
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
