目录
- Pimpl惯用法
- 不要在构造函数或析构函数中调用虚函数,这些调用不会指向子类。
- 渐进公开原则:
- 使用枚举类型代替布尔类型,提高代码可读性
- RAII
- 平台性
- 回调、观察者、通知
- 观察者模式详解
- 通用设计模式
- 命名参数惯用法(Named Parameter Idiom, NPI)
- 异常处理注意事项
- API风格
将所有的私有数据成员隔离到一个.cpp中独立实现的类或结构体,.h文件仅需要包含指向该实例的不透明指针即可。
不要在构造函数或析构函数中调用虚函数,这些调用不会指向子类。
渐进公开原则:
使用枚举类型代替布尔类型,提高代码可读性
int Func(const std::string& text, bool search_forward, bool case_sensitive);
===>
// 用户很容易忘记第一个布尔型参数是搜索方向还是区分大小写的标记。
// 使用错误的顺序传递标记将导致不法预料的行为,在用户意识到自己颠倒
// 了布尔型参数之前,他们很可能会把时间浪费在调试程序上。
enum SearchDirection {
FORWARD,
BACKWARD
};
enum CaseSensitivity {
CASE_SENSITIVE,
CASE_INSENSITIVE,
};
result = Func(text, FORWARD, CASE_INSENSITIVE);
比
result = Func(text, true, false);
更加直观。
// 对于enum不能解决的复杂情况,为了确保每个参数都有唯一的类型,
// 甚至可以引人新类。
API设计中如果涉及到资源分配,可以提供一个类来管理这些操作。
或者提供共有的Release()方法让客户控制何时释放资源
平台性
class MobilePhone {
public:
bool StartCall(const std::string& number);
bool EndCall();
bool HasGPS() const;
bool GetGPSLocation(double lat, double lon);
};
bool MobilePhone::HasGPS() const
{
#if defined TARGET_OS_IPHONE
return true;
#else
return false;
#endif
}
回调、观察者、通知
回调:模块A中的一个函数指针被传递给模块B,B就能在合适的时间调用A中的函数。
模块B对于A一无所知,对A也没有包含or链接的依赖。
回调的性质可以使得低层代码执行与其无依赖的高层代码。
闭包:模块A传递给B的一条数据,数据包含在A提供给B的回调函数中。
观察者模式,对象维护一个它依赖的对象(观察者)列表,通过调用观察者的方法通知观察者。
// boost::signal创建一个没有参数的信号,将一个对象连接到信号上,最终发出该信号会调用Myslot::operator(), // 进而会打印一条信息到标准输出上。 class Myslot { public: void operato()() const { std::cout << "Myslot called" << std::endl; } }; Myslot slot; boost::signal<void()> signal; // 链接槽和信号 signal.connect(slot); // 发出信号从而调用所有的槽 signal(); // 低层次的类创建并拥有信号,然后允许其他类成为该信号的槽, // 低层次类在任意时间发出信号,进而所有链接的槽都会被调用观察者模式详解
主题为多个不同的消息类型注册并发出通知,这样就可以只订阅他们关心的特定内容。
#include "observer.h" class MySubject : public ISubject { public: enum Messages {ADD, REMOVE}; };继承IObserver抽象基类并实现Update()方法来创建观察者对象。
通用设计模式
命名参数惯用法(Named Parameter Idiom, NPI)
让setter方法返回对象本身的引用(return *this),这样就能把一系列方法调用链接到一起,减少代码量,如:
异常处理注意事项
- 从std::exception类派生出自己的异常,定义what()方法描述失效信息
- 采用RAII来维护异常安全性,确保抛出异常时资源能够正常清理
- 确保在函数的计算中将它可以抛出的异常进行文档记录
- 以引用的形式捕获异常,避免调用抛出对象的复制构造函数
No comments yet.