类
1. virtual destructor
让base class 的 destructor 为 virtual, 除非你确定不会有人企图通过一个pointer to base 去删除一个derived object。
基类的析构函数要么是虚拟共有函数,要么是非虚拟的保护函数
为广泛运用classes, 最好使用编译器防火墙的手法(compiler-firewall idiom)来这掩实做细节。使用一个不透明的指针(指向一个已经声明但未定义的class),将之宣告为struct XxxxImpl* pimpl; 用来存放private member(包括state variables 和 member functions)
1)即使虚函数是私有的, 你也不能把虚函数隐藏在pimpl类中, 如果想要虚函数复写基类中的同名虚函数, 那么该虚函数必须出现在真正的派生类。 如果虚函数不是继承来的,那么为了让之后的派生类能复写他,其还是必须出现在可见类中。
2)如果pimpl中的函数要使用其他函数, 其可能需要一个指向可见对象的反向指针。
实现Pimpl的最好手法就是使用指针,同时还将动态资源安全的包装在一个管理者对象中smart pointer
绝对不要以public inheritance 复用 base class 内的代码, public inheritance 是为了被那些以多态的方式运用的base object 的代码复用。
如果实现is implemented in terms of 的关系, 请选择membership/aggregation, 而不要用inheritance, 只有在绝对必要的情况下才使用private inheritance - 也就是说当你需要存取protected members 或是需要改写虚函数时。
一般形式:
T& T::operator=(const T& rhs){
// 检查对自己赋值的情况
if (*this == rhs) // 假设operator=存在
return *this;
...
return *this;
低耦合性提高程序的正确性,包括异常安全, 高耦合性降低程序的最大可能的正确性,包括异常安全。
1)结合使用程序模块或程序库
2)protocol类(interface 类),完全由纯虚函数构成, 没有数据成员
3)易于多态使用
private的可访问性:
具有对某个成员的访问权的代码可以通过泄露该成员的指针的方式将其访问权限授予其他任何代码。
成员的名字只对其所属类的其他成员或者友元来说是可访问的, 而这里的其他成员也包括成员模板的任何显示特化。
尽量将虚函数设置为私有的, 只有当派生类需要调用基类中实现的虚函数的时候, 我们才将后者设为保护的。
class B{int y;};
class C : public A, public B{int z;};
int _tmain(int argc, _TCHAR* argv[]){
A *aa;
B *bb;
C cc;
aa = &cc;
bb = &cc;
return 0;
}
aa==bb ?
静态成员函数指针,和普通的C函数指针没什么两样
class Foo
{
public:
static int foo();
};
int (*fp)() = Foo::foo();
因为静态成员函数的执行和类的对象无关,也没有隐藏的对象指针参数
非静态成员函数,因为有隐藏的对象指针参数,就有点不一样
class Foo
{
int foo1();
int foo2(long);
};
为了代码的简洁,最好用typedef先定义指针类型
typedef int (Foo::*fpType1)(); //Foo类返回类型为int,参数列表为空的成员函数指针类型
typedef int (Foo::*fpType2)(long); //Foo类返回类型为int,参数列表为long的成员函数指针类型
然后就可以声明指向成员函数的指针
fpType1 fp1 = &Foo::foo1;
fpType2 fp2 = &Foo::foo2;
通过成员函数调用的时候注意,因为非静态的成员函数执行实际上是需要一个类对象的
Foo f;
int result = (f.*fp1)();
或者通过对象指针
Foo f2 = &f;
int result2 = (f2->*fp1)();
类对象的成员函数能够提供灵活的对成员函数的调用,今天写一个测试程序,为了这个测试程序的“扩展性”,研究成员函数指针花了一些时间,最后还是用别的方法来实现“扩展性”。虽然C++提供了这种个功能,我觉得还是尽量不要使用的好,程序不大容易读,就算我懂,将来维护代码的同僚未必明白,所以成员函数指针,能不用还是不用的好。
让base class 的 destructor 为 virtual, 除非你确定不会有人企图通过一个pointer to base 去删除一个derived object。
基类的析构函数要么是虚拟共有函数,要么是非虚拟的保护函数
2. 绝不要改写虚函数的预设参数
3. 尽量避免使用public 虚函数, 尽量以template method 取代之
为广泛运用classes, 最好使用编译器防火墙的手法(compiler-firewall idiom)来这掩实做细节。使用一个不透明的指针(指向一个已经声明但未定义的class),将之宣告为struct XxxxImpl* pimpl; 用来存放private member(包括state variables 和 member functions)
1)即使虚函数是私有的, 你也不能把虚函数隐藏在pimpl类中, 如果想要虚函数复写基类中的同名虚函数, 那么该虚函数必须出现在真正的派生类。 如果虚函数不是继承来的,那么为了让之后的派生类能复写他,其还是必须出现在可见类中。
2)如果pimpl中的函数要使用其他函数, 其可能需要一个指向可见对象的反向指针。
实现Pimpl的最好手法就是使用指针,同时还将动态资源安全的包装在一个管理者对象中smart pointer
5. class relationships
绝对不要以public inheritance 复用 base class 内的代码, public inheritance 是为了被那些以多态的方式运用的base object 的代码复用。
如果实现is implemented in terms of 的关系, 请选择membership/aggregation, 而不要用inheritance, 只有在绝对必要的情况下才使用private inheritance - 也就是说当你需要存取protected members 或是需要改写虚函数时。
6. 拷贝构造函数和拷贝赋值
一般形式:
T& T::operator=(const T& rhs){
// 检查对自己赋值的情况
if (*this == rhs) // 假设operator=存在
return *this;
...
return *this;
}
低耦合性提高程序的正确性,包括异常安全, 高耦合性降低程序的最大可能的正确性,包括异常安全。
8. 多继承
1)结合使用程序模块或程序库
2)protocol类(interface 类),完全由纯虚函数构成, 没有数据成员
3)易于多态使用
9. 访问权限控制
private的可访问性:
具有对某个成员的访问权的代码可以通过泄露该成员的指针的方式将其访问权限授予其他任何代码。
成员的名字只对其所属类的其他成员或者友元来说是可访问的, 而这里的其他成员也包括成员模板的任何显示特化。
10. 封装
总是将所有数据成员放在私有区段。
11. virtual
尽量让接口成为非虚的。尽量将虚函数设置为私有的, 只有当派生类需要调用基类中实现的虚函数的时候, 我们才将后者设为保护的。
12. 继承
13. constructor/destructor call virtual function
14. inline virtual" member functions
15.多继承
class B{int y;};
class C : public A, public B{int z;};
int _tmain(int argc, _TCHAR* argv[]){
A *aa;
B *bb;
C cc;
aa = &cc;
bb = &cc;
return 0;
}
aa==bb ?
16. 成员函数指针
静态成员函数指针,和普通的C函数指针没什么两样
class Foo
{
public:
static int foo();
};
int (*fp)() = Foo::foo();
因为静态成员函数的执行和类的对象无关,也没有隐藏的对象指针参数
非静态成员函数,因为有隐藏的对象指针参数,就有点不一样
class Foo
{
int foo1();
int foo2(long);
};
为了代码的简洁,最好用typedef先定义指针类型
typedef int (Foo::*fpType1)(); //Foo类返回类型为int,参数列表为空的成员函数指针类型
typedef int (Foo::*fpType2)(long); //Foo类返回类型为int,参数列表为long的成员函数指针类型
然后就可以声明指向成员函数的指针
fpType1 fp1 = &Foo::foo1;
fpType2 fp2 = &Foo::foo2;
通过成员函数调用的时候注意,因为非静态的成员函数执行实际上是需要一个类对象的
Foo f;
int result = (f.*fp1)();
或者通过对象指针
Foo f2 = &f;
int result2 = (f2->*fp1)();
类对象的成员函数能够提供灵活的对成员函数的调用,今天写一个测试程序,为了这个测试程序的“扩展性”,研究成员函数指针花了一些时间,最后还是用别的方法来实现“扩展性”。虽然C++提供了这种个功能,我觉得还是尽量不要使用的好,程序不大容易读,就算我懂,将来维护代码的同僚未必明白,所以成员函数指针,能不用还是不用的好。