8、成员函数形参表和函数体处于类作用域中,这两个可以直接使用类内定义的类型或者变量。函数的返回值类型不一定在类作用域中,与形参表相比,返回值类型出现在成员函数名字前面。如果函数定义在类定义体外,则用于返回值类型的名字在类作用域之外。如果返回值类型使用类定义的类型,则必须使用完全限定名。而形参表和成员函数体都出现在成员名之后,这些都是泪的作用域中定义,所以不用限定而使用其他成员。如:
class Screen{
public:
Typedef std::string::size_type index;
Index get_cursor() const;
private:
Int cursor;
};
Inline Screen::index Screen::get_cursor()const{
return cursor;
}
9、一旦一个名字被用作类型名,该名字就不能被重复定义。构造函数不能声明为const,因为这完全没有意义,构造函数的性质就是要给数据成员进行赋值的。
10、构造函数可以用初始化列表或函数体内赋值进行初始化。但赋值并不是显式的初始化,而是构造函数执行时先对数据成员进行默认初始化,然后再赋值覆盖。从概念上讲,可以认为构造函数分为两个阶段执行:初始化阶段;普通计算阶段。计算阶段由构造函数函数体中的语句组成。不管数据成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段进行初始化。初始化发生在计算阶段之前。
11、根据上述规定,可以得出:有些成员必须在构造函数初始化列表中进行初始化。对于这样的成员,在构造函数体重对它们初始化不起作用。没有默认构造函数的类类型的成员,const或者引用类型成员必须在构造函数初始化列表中进行初始化,而不能在构造函数函数体中进行赋值初始化。
12、数据成员初始化的顺序和数据成员声明的顺序一致,而不是根据构造函数的初始化列表的顺序一致。
13、只要定义一个对象时没用提供初始化式,就使用了该类的默认构造函数。如:A a;使用的是默认构造函数,而A a(37);表示使用了其他构造函数。
14、只有类没有定义构造函数时,编译器才会自动生成一个默认构造函数。
15、单个实参调用的构造函数定义了从形参类型到该类类型的一个隐式转换。如:
class Sales_item{
public:
sales_item(const std::string &book=""):isbn(book),unit(0),revenue(0.0){}
void same_isbn(Sales_item si);
};
//当使用对象调用
Sales_item item;
Item.same_isbn("123556");
//就会调用sales_item的单形参的构造函数实例化一个新对象,然后传给same_isbn做实参。从而实现隐式转换。若要避免隐式转换,就要在构造函数声明前加上expl//icit,explicit用于类内部的构造函数声明上,在类定义体外部不再重复。
16、友元只能出现在类定义的内部。
17、当我们在类外部定义static成员时,无需重复指定static保留字,该保留字只出现在类定义体内部声明处。static成员函数不能被声明为const,因为const就是承诺不会修改该函数所属对象的数据成员,但是static 不属于任何对象,static不能声明为虚函数。static成员可以通过作用域操作符,对象,引用或指向该类类型的对象的指针调用。
18、static成员函数没有this形参,它可以直接访问所属类的static成员,但不能直接使用非static成员。
19、当static成员在类外部定义时,static只写在类定义体内部的声明处。
20、static数据成员只能定义在类定义体外部,并且进行初始化,static只能在声明处标识。因为普通数据成员不能在类的定义体中初始化,但static成员定义时必须初始化,所以只能定义在定义体外部。
21、const static数据成员可以在类定义体内部进行初始化,但是数据成员必须在类定义体外部进行定义。只是在类内部初始化时,数据成员的定义不再指定初始值。
22、static数据成员可以做默认实参,其他数据成员不可以。
23、static数据成员的类型可以是该类成员所属的类型,如:
class Bar{
public:
private:
static Bar men1;//ok
Bar * men2;//ok
Bar men3;//error
};
复制控制
1、若要禁止复制,必须声明其复制构造函数为private,若想友元和成员中的复制也禁止,就可以声明但是不定义一个private的复制构造函数。
2、如果没有显式定义复制构造函数或者赋值操作符,编译器通常会提供一个默认的。
3、当定义一个新对象,并用一个同类型的对象对他进行初始化时,将显式使用复制构造函数;当将该类型的对象传递给函数或从函数返回值返回该类型的对象时,将隐式使用复制构造函数。
4、使用未定义的成员的任何尝试将导致链接错误。
5、如果定义了复制构造函数,编译器不会自动生成默认构造函数,所以要自己定义默认构造函数。
6、合成析构函数并不删除指针成员所指向的对象。
7、即使编写了自己的析构函数,合成析构函数仍然运行。当撤销对象时,先运行自定义的析构函数,然后运行合成析构函数。
重载操作符
1、::,.*,., :不可重载。
2、重载操作符必须具有一个类类型的操作数或枚举类型。优先级和结合性是固定的且不具备短路求值的特征。
3、除了函数调用操作符operator()之外,重载操作符时使用默认实参是非法的。
4、操作符定义为非成员函数时,通常必须将它们设置为所操作类的友元。为的是可以访问类的私有成员。
5、=,(),[],->操作符必须定义为成员,将这些操作符定义为非成员函数将在编译时标记为错误。而复合赋值操作符如+=通常定义为成员,但是定义为非成员,编译时不会出错。改变对象状态的操作符如自增操作符要定义为成员函数。算数的,相等的,关系操作符位操作符一般定义为普通函数。箭头操作符必须定义为类的成员函数,解引用操作符不要求定义成员。()调用操作符必须声明为成员函数,一个类可以定义多个调用操作符版本。定义了调用操作符的类,其对象称为函数对象。即它的行为是类似函数的对象。
6、为了与内置类型保持一致,加法返回一个右值,而不是一个引用。
7、类定义下标操作符时,一般需要定义两个版本:一个为非const成员并返回引用;一个味const成员并返回const引用。
8、前缀操作符:A& operator++();.后缀操作符:A& operator++(int);int形参只是一个标识,没有实际用途。
9、转换操作符 operator type();type表示内置类型名,类类型名,由类型别名定义的名字。对任何可作为函数返回类型的类型(除了void外)都可以定义转换函数。不允许转换为数组类型或函数类型。转化为指针类型(数据或函数指针)以及引用类型时可以的。转换操作符函数必须是成员函数,不能指定返回类型,形参表为空。
10、只能用一个类类型转换,即,定义a能转换为b,b能转换为c,但a不能转换为b再转换为c.