const 成员变量的用法和普通 const 变量的用法相似
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值
一旦将对象定义为常对象之后,不管是哪种形式,该对象就只能访问被 const 修饰的成员了(包括 const 成员变量和 const 成员函数),因为非 const 成员可能会修改对象的数据(编译器也会这样假设),C++禁止这样做。
1. 即使是一个抽象基类,如果它有非静态数据成员,也应该给它提供一个带参数的构造函数,来初始化它的数据成员。或许你可以通过其派生类来初始化它的数据成员(假如nostatic data member为publish或protected),但这样做的后果则是破坏了数据的封装性,使类的维护和修改更加困难。由此引申,类的data member应当被初始化,且只在其构造函数或其member function中初始化。
2.不要将析构函数设计为纯虚的,这不是一个好的设计。将析构函数设计为纯虚函数意味着,即使纯虚函数在语法上允许我们只声明而不定义纯虚函数,但还是必须实现该纯虚析构函数,否则它所有的继承类都将遇到链接错误。一个不能派生继承类的抽象类有什么存在的意义?必须定义纯虚析构函数,而不能仅仅声明它的原因在于:每一个继承类的析构函数会被编译器加以扩展,以静态调用方式其每一个基类的析构函数(假如有的话,不论是显示的还是编译器合成的),所以只要任何一个基类的析构函数缺乏定义,就会导致链接失败。矛盾就在这里,纯虚函数的语法,允许只声明而不定义纯虚析构函数,而编译器则死脑筋的看到一个其基类的
析构函数声明,则去调用它的实体,而不管它有没有被定义。
3.真的必要的时候才使用虚函数,不要滥用虚函数。虚函数意味着不
小的成本,编译很可能给你的类带来膨胀效应:
4.不能决定一个虚函数是否需要 const ,那么就不要它。
**5.决不在构造函数或析构函数中使用虚函数机制。**在构造函数中,每次调用虚函数会被决议为当前构造函数所对应类的虚函数实体,虚函数机制并不起作用。当一个base类的构造函数含有对虚函数vf()的调用,当其派生类derived的构造函数调用基类base的构造函数的时候,其中调用的虚函数vf()是base中的实体,而不是derived中的实体。这是由vptr初始化的位置决定的——在所有基类构造函数调用之后,在程序员供应的代码或是成员初始化队列之前。因构造函数的调用顺序是:有根源到末端,由内而外,所以对象的构造过程可以看成是,从构建一个最基础的对象开始,一步步构建成一个目标对象。析构函数则有着与构造相反的顺序,因此在构造或析构函数中使用虚函数机制,往往不是程序员的意图。若要在构造函数或析构函数中调用虚函数,应当直接以静态方式调用,而不要通过虚函数机制。
Plain Old Data(简旧数据类型) : 能直接以其二进制形式与 C 库交互的数据类型,比如可以直接使用memmove、memcopy等C函数进行复制。
class Point {
float x,y,z;
};
概念上来讲,对于一段这样的C++代码,编译器会为之合成一个默认构造函数、拷贝构造函数、析构函数、赋值操作符。然而实际上编译器会分析这段代码,并给Point贴上Plain OId Data标签。编译器在此后对于Point的处理与在C中完全一样,也就是说上述的函数都不会被合成。可见概念上应当由编译器合成的函数,并不一定会合成,编译器只有在必要的时候才会合成它们。由此一来,原本在观念上应该调用这些函数的地方实质上不会调用,而是用其它的方法来完成上面的功能,比方复制操作会用bitwise copy(位拷贝)。
struct N{
int x,y,z;
};
//或者
class N{
public:
int x,y,z;
};
int main(){
N a={1,2,3};
return 0;
}
限制:1)只有成员都是public,且没有构造函数时才能使用,2)只能指定常量。

根据c++ 语法,Point 的初始化应有most-derived class来施行。也就是说当Vertex3d为most-derived class的时候,应当由它的构造函数来调用Point的构造函数初始化Point子对象,Vertex3d的子对象的构造函数对于Point的调用则应当抑制。如果没有抑制会怎么样?当我们定义Vertex3d cv;时,Vertex3d的构造函数中调用Point的构造函数、而随之调用它的子对象,Point3d和Vertex的构造函数中也调用了Point的构造函数。先不说,对于同一个子对象进行三次初始化是否有效率,更重要的是,这将不可避免的带来错误。由Vertex3d指定的子对象Point的值,会被覆盖掉。
编译器通常使用一个条件变量来表示是否为most-derived class,各构造函数根据这个条件变量来决定是否调用虚基类的构造函数,因此通过控制这个条件变量,就可以抑制非most-derived class调用虚基类的构造函数。当然也有其它的方法来做同样的事。
设计一个类,并考虑到要以一个对象指定给另一个对象时,有三种选择:
对于第三点,只要将赋值操作符声明为private,且不定义它就可以了。对于第二点,只有在第一点的行为不安全或不正确,或你特别想往其中插入点东西的时候。
编译器的默认行为:如果没有特殊情况,用bitwise copy(展现bitwise copy语意),否则合成赋值运算符。
不使用bitwise copy的四种特殊情况:
如果class没有定义 destructor,那么只有在class内带的member object(或是class 自己的base class)拥有destructor的情况下,编译器才会自动合成出一个来。否则,destructor会被视为不需要,也就不需被合成(当然更不需要被调用)。
析构的顺序正好与构造相反:
析构函数实现策略:维护两份析构函数实例
对于完整对象实例:总是设定好vptr,并调用虚基类析构函数。
基类子对象实例:除非析构函数中调用了虚函数,否则不会设定vptr。