也许只是一些技巧而已,不过值得反复重用就变成语言的Idioms 了。说到Idioms,POSA 认
为Pattern 可以分为三个层次(或者粒度),Architecture patterns、Design patterns、Programming
language Idioms。也就是说Idioms 很多是跟语言相关的。
1、实现抽象类(不允许实例化)
这个可能大家都知道,把构造函数声明为protected 。(当然如果类中包含纯虚函数自然就不
能实例化,但是有的抽象类需要为虚函数提供缺省实现,因此可能不包含纯虚函数。)
2、实现final 类(不允许被派生)
namespace Private{
class NonDerivableHelper
{
NonDerivableHelper() {}
friend class NonDerivable;
};
}
#ifdef NDEBUG
#define FINAL_CLASS
#else
#define FINAL_CLASS : private virtual Private::NonDerivableHelper
#endif
class NonDerivable FINAL_CLASS
{
...
};
这里namespace并非必须,只是一个比较好的习惯而已。
3、实现禁止拷贝构造和赋值操作符
class MyClass
{
private:
MyClass(const MyClass& );
const MyClass& operator = ( const MyClass& );
};
为了防止成员函数调用操作,这两个函数应该只有声明没有实现。
C++中的Idioms 很多很多,比如TypeTraits、SmartPointer 这些都可以视为经典的 Idioms 。注:关于第二个实现 final 类的方式,只要是 virtual继承即可,至于是 private、protected
还是 public关系不大。在 comp.lang.c++.moderated (2001/5/15)上,Andrei Alexandrescu 有他
的见解,他不赞成上面文章中使用的 friend-based 方式,直接去掉 friend 那一行,这时必须采用
private virtual 继承方式。private virtual 继承确实使得 没有任何类 能只继承
NonDerivable。
class D: public NonDerivable
{
D() {} //编译错误
}
不过多重虚拟继承又绕了过去
class D FINAL_CLASS, public NonDerivable
{
D() {} //一切正常
}
Andrei Alexandrescu 又提出了一个非常巧妙的办法:把 Private::NonDerivableHelper
的构造函数加一个参数,改为 NonDerivableHelper(int) {},然后把 NonDerivable 的
构造函数写成 NonDerivable(): NonDerivableHelper(0) {}
#ifdef NDEBUG
#define FINAL_CLASS
#else
#define FINAL_CLASS : private virtual Private::NonDerivableHelper
#endif
namespace Private
{
class NonDerivableHelper
{
protected:
NonDerivableHelper(int) {} //ADDED CTOR ARGUMENT
};
}
class NonDerivable FINAL_CLASS
{
public:
NonDerivable() : NonDerivableHelper(0) {} //PASS A DUMMY VALUE
};