ToB企服应用市场:ToB评测及商务社交产业平台

标题: 《Effective C++》第三版-4. 设计与声明(Design and Declarations) [打印本页]

作者: 美食家大橙子    时间: 2024-5-19 00:23
标题: 《Effective C++》第三版-4. 设计与声明(Design and Declarations)
目次

条款17:让接口容易被精确使用,不易被误用(Make interfaces easy to use correctly and hard to use incorrectly)

限制类型和值
  1. class Date {
  2. public:
  3.         Date(int month, int day, int year);  //可能月日年顺序错,可能传递无效的月份或日期
  4.         ...
  5. };
复制代码
可使用类型系统(type system)规避以上错误,即引入外覆类型(wrapper type)区别年代日:
  1. struct Day {
  2. explicite Day(int d)
  3.         : val(d) { }
  4. int val;
  5. }
  6. struct Month {
  7. explicite Month(int m)
  8.         : val(m) { }
  9. int val;
  10. }
  11. struct Year{
  12. explicite Year(int y)
  13.         : val(y) { }
  14. int val;
  15. }
  16. class Date {
  17. public:
  18.         Date(const Month& m, const Day& d, const Year& y);  //可能月日年顺序错,可能传递无效的月份或日期
  19.         ...
  20. };
  21. Date d(Month(3), Day(30), Year(1995));  //可有效防止接口误用
复制代码
保证了类型精确之后,需要保证输入的值有用:
  1. class Month {
  2. public:
  3.         static Month Jan() { return Month(1); }
  4.         static Month Feb() { return Month(2); }
  5.         ...
  6.         static Month Dec() { return Month(12); }
  7.         ...
  8. private:
  9.         explicit Month(int m);
  10.         ...
  11. };
  12. Date d(Month::Mar(), Day(30), Year(1995));
复制代码
规定能做和不能做的事
  1. if ( a * b = c) ...  //以const修饰操作符*,使其不能被赋值
复制代码
提供举动一致的接口

为了避免忘记删除或者重复删除指针,可令工厂函数直接返回智能指针:
  1. Investment* createInvestment(); //用户可能忘记删除或者重复删除指针
  2. std::tr1::shared_ptr<Investment> createInvestment();
复制代码
若盼望用自定义的getRidOfInvestment,则需要避免误用delete,可思量将getRidOfInvestment绑定为删除器(deleter):
删除器在引用次数为0时调用,故可创建一个null shared_ptr
  1. std::tr1::shared_ptr<Investment> createInvestment()
  2. {
  3.         std::tr1::shared_ptr<Investment> retVal(static_cast<Investment*>(0),
  4.                                                                                                                                                                         getRidOfInvestment);  //创建一个null shared_ptr
  5.         retVal = ... ;  //令retVal指向目标对象
  6.         return retVal;
  7. }
复制代码
若pInv管理的原始指针能在pInv创立之前确定下来,则将原始指针直接传递给pInv的构造函数更好
tr1::shared_ptr会主动使用每个指针专属的删除器,从而无须担心cross-DLL problem:
cross-DLL problem:对象在动态毗连程序库(DLL)中被new创建,但在另一个DLL内被delete销毁
  1. //返回的tr1::shared_ptr可能被传递给任何其他DLL
  2. //其会追踪记录从而在引用次数为0时调用那个DLL的delete
  3. std::tr1:;shared_ptr<Investment> createInvestment()
  4. {
  5.         return std::tr1::shared_ptr<Investment>(new Stock);
  6. }
复制代码
Boost的tr1::shared_ptr特点:
Tips:
条款19:设计class犹如设计type(Treat class design as type design)

定义一个新class时也就定义了一个新type。设计高效的类需要思量以下题目:
Tips:
条款20:宁以pass-by-reference-to-const更换pass-by-value(Prefer pass-by-reference-to-cons to pass-by-value)

避免构造和析构
  1. class Person {
  2. public:
  3.         Person();
  4.         virtual ~Person();
  5.         ...
  6. private:
  7.         std::string name;
  8.         std::string address;
  9. };
  10. class Student: public Person {
  11. public:
  12.         Student();
  13.         ~Student();
  14.         ...
  15. private:
  16.         std::string schoolName;
  17.         std::string schoolAddress;
  18. };
  19. bool validateStudent(Student s);  //会调用六次构造函数和六次析构函数
  20. bool validateStudent(const Student& s);  //效率提升很多
复制代码
上述代码validateStudent函数中pass-by-value会调用六次构造函数和六次析构函数:
使用pass-by-reference可避免频繁构造和析构
避免对象切割

对象切割(slicing):派生类以值传递并被视为基类对象时,回调用基类的构造函数,而派生类的成分全无
[code]class Window {public:        ...        std::string name() const;  //返回窗口名称        virtual void display() const;  //显示窗口和其内容};class WindowWithScrollBars: public Window {public:        ...        virtual void display() const;};void printNameAndDisply(Window w){        std::cout




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4