a. C++由四个主要次语言组成: C. Object-Oriented C++(类,封装,继承,多态,virtual函数等). Template C++. STL(容器(containers),迭代器(iterators),算法(algorithms)以及函数对象(function objects))。
b. 这四个次语言,当你从某个次语言切换到另一个,导致高效编程守则要求你改变策略。C++高效编程守则视状况而变化,取决于你使用C++的哪一部分
a. #define当编译出错时,目标码出现多份,跟踪难度大,因为所使用的名称可能并未进入记号表(symbol table),处理方法:例:#define ASPECT_RATIO 1.653 --> (语言常量) const double AspectRatio = 1.653;
b. 对于单纯常量,最好以const对象或enums替换#defines;定义常量指针时采用如下两种方法: const char* const authorName = ”yxstars“. const std::string authorName(”yxstars“)例:#define CALL_WITH_MAX(a,b) f((a) > (b)) ? (a) : (b)) --> template<typename T> inline void callWithMax(cosnt T &a, cosnt T &b) { f(a > b ? a : b); }
a. 将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体;
b. 编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的常量性”(conceptual constness);
a. 为内置型对象进行手工初始化,因为C++不保证初始化它们;
b. 构造函数最好使用成员初始化列表,而不要在构造函数本体内使用赋值操作。初始化列表列出的成员变量,其排列次序应该和它们在类中的声明次序相同;
c. 为免除“跨编译单元之初始化次序”问题,以local static对象代替non-local static对象;
fileSystem& tfs(){ static fileSystem fs; return fs; }
a. 编译器可以暗自为类创建默认构造函数、拷贝构造函数、拷贝赋值操作符,以及析构函数。
class Uncopyable(){ protected: Uncopyable(){} ~Uncopyable(){} Private: Uncopyable(const Uncopyable&); //zhu zhi copying Uncopyable& operator=(const Uncopyable&); }; class HomeYxstars: private Uncopyable{ ...... };
DBConn::DBConn(){ try{db.close();} catch(...){ std::abort(); //捕获异常,强迫结束程序或什么也不做 } }
a. 在构造和析构函数期间不要调用虚函数,因为这类调用从不下降至派生类。
b. 基类的构造函数要早于派生类的构造函数运行,当基类的构造函数执行时,派生类的成员变量尚未初始化。指向虚函数表的指针vptr没被初始化不能去调用派生类的virtual函数。
Widget & operator = (const Widget &rhs) { ... return *this; }
a. 确保当对象自我赋值时operator =有良好行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy-and-swap。
b. 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。Widget& Widget::operator=(const Widget& rhs) { delete pb; //这里对pb指向内存对象进行delete,试想 *this == rhs?,不安全 pb = new Bitmap(*rhs.pb); return *this; }
Widget& Widget::operator=(const Widget& rhs) { if (this == &rhs) return *this; //试同测试 delete pb; pb = new Bitmap(*rhs.pb); return *this; }
Widget& Widget::operator=(const Widget& rhs) { Bitmap *pOrig = pb; //记住原先的pb pb = new Bitmap(*rhs.pb); //令pb指向*pb的一个复本 delete pOrig; //删除原先的pb return *this; //这样既解决了自我赋值,又解决了异常安全问题。自我赋值,将pb所指对象换了个存储地址。 }
class Widget(){ ... void swap(Widget& rhs); ... } widget& widget::operator=(cosnt widget& rhs) { widget temp(rhs); swap(temp); return *this; }
a. 如果你在类中添加一个成员变量,你必须同时修改相应的copying函数(所有的构造函数,拷贝构造函数以及拷贝赋值操作符)。
b. Copying函数应该确保复制“对象内的所有成员变量”及“所有基类成员”;
c. 不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放进第三个函数中,并由两个copying函数共同调用。
d. 另copy assignment操作符调用copy构造函数是不合理的,因为这就像试图构造一个已经存在的对象。反过来同样无意义。
文/yanxin8原创,获取更多信息请移步至yanxin8.com...