当前位置:首页 > effectiveC++
class A{};
voiddel_func(A *a){
cout<<\删|?除y对?象¨?\< void test(){ A *a = new A; shared_ptrpa(a,del_func); } NO15 在资源类中提供对原始资源的访问 1、显示转换,.get() -> *等等: class A{ public: A():a(7){} void display(){cout<<\值|ì:êo \< void test(){ A *a = new A; shared_ptrpa(a); cout< cout<<(*pa).a< 2、隐式转换 class DB{ public: DB():name(\){} string name; }; classDBManager{ public: DBManager(DB &d):data(d) {} operator DB() const{ return data; } DB get(){return data;} private : DB data; }; voidprint_db(DB d){ cout< void test(){ DB d; DBManagerdbm(d); print_db(dbm.get()); //显示转换 print_db(dbm); //通过重载运算符()的隐式转换 print_db(dbm.operator DB()); //和上面一句是等价的 } NO16 delete 与delete[] 1、删除数组指针要用 delete [] 2、注意typedef导致的混淆 typedef string AddressLines[4]; string* pal=new AddressLines; //等价于string *pal = new string[4]; delete [] pal //但是如果没有看到typedf语句的话很容易把pal当成一个string的指针,从而写出了:delete pal; NO17 以独立语句将new对象置入智能指针 class Widget{}; intget_priority(){ staticinti=0; returni++; } voidprocessWidget(std::tr1::shared_ptr void test(){ //错误做法:因为编译器并没有确定processWidget前后两个参数产生顺序,如果 //get_priority()调用在new widget和构造shared_ptr直接发送异常会导致内存泄漏。 //processWidget(std::tr1::shared_ptr NO18 让接口容易被正确使用 1、导入新类型以预防客户端错误 2、避免与内置类型不一致 eg:重载operator*()需要加上修饰符const,以使得a*b=c不合法 3、使用shared_ptr,直接返回包装好的指针(且同时制定删除器而不是由用户对shared_ptr进行删除) NO19略 NO20 用const的引用传递代替值传递 1、值传递的函数使用的是传递过来对象的副本,所以函数不能能改变他,因此换做引用传递时必须保证是const XXX& x. 2、引用传递还可以防止对象切割导致的问题: class People{ public: virtualvoid speak()const {cout<<\< class Chinese: public People{ public: void speak() const {cout<<\我是中国人\< //Chinese p func(p)只能输出\people\因为根据实参构造形参时把base class //以外的部分切割了。 voidfunc(People p){ p.speak(); } //可以正常运行 voidfunc(const People &p){ p.speak(); } 当然了,通过这种方法是调用的必须是const成员函数(因为不管事值传递还是const引用传递都不可能改变原来的对象)。 3、pass-by-value成本不高的集中情况:内置类型、STL的迭代器、函数对象 NO21 必须返回对象时别妄想返回其引用 几种错误情况: 1、Studen& get(){ Student s(“name”,13); return s; } 这样返回的引用指向的student在函数返回时就已经被析构了 即使函数内设置static Student也有问题(多线程安全性、两次get()所得对象无法比较) 2、Student& get(){ Student *s = new Student(“name”,13); return s; } 这样删除Student对象变得很困难。尤其是x*y*z这种隐藏的指针根本无法删除。 NO22 将成员变量声明为private 1、提高封装性,改变实现后用户代码可以保存不变 2、其实protected和public一样会带来封装性的严重下降 NO23 用非成员函数、非友元替换成员函数 1、no-member相比于member函数可以使更少的代码访问类的private成员 2、采用no-member函数,并将不同作用的non-member函数分布在不同的头文件中会有效提高扩展性: NO24 若参数均需类型转换,改用non-member函数 1、 class Rational{ public: Rational(int numerator=0,int denominator=1): nu(numerator),de(denominator){} int numerator() const {return nu;} int denominator() const{return de;} private: int nu; int de; }; 若Rational中增加一个成员函数operator* : const Rational opeartor(const Rational &rhs){ return Rational(nu*rhs.nu,de*rhs.de); } 则: Rational r4 =r*2; Rational r5 = 2*r; //正确 //错误 这是因为:只有当参数被列于参数列时,他才是隐式转换的合格参与者,因此r*2中的2被当成了operator*(const Rational &)中的参数。而2*r中的2不在参数列表中。 2、正确做法:改成non-member函数: const Rational operator*(const Rational &lhs,const Rational &rhs){ Rational r(lhs.numerator()*rhs.numerator(),lhs.denominator()*rhs.denominator()); return r; } 此时2*r也可以正确运行 tips:这个non-member函数不需要作为友元,因为他可以通过函数访问nu,de.
共分享92篇相关文档