上一篇未完的等看完section 13 copy control 再彻底更新。
类内定义(defined)的成员函数默认是内联的(inline),编译器在实际编译时可以忽略。内联函数在编译时做类似宏替换的工作,通常是把常用的,简单的函数定义成内联的,像比较大小一类的。在类外定义内联函数需在函数返回值前加inline,如inline int myclass::a()。类外定义(实现)的内联函数须和类声明一起写在头文件中,而不是源文件。
成员函数后跟有const的为常成员函数,形如 int a() const.常成员函数只能对类数据成员进行读操作,常成员函数的参数列表中隐含传输了 const this指针。类的成员函数返回值是本类类型或其的引用时,函数体内可return *this,常成员函数返回*this,返回的就是常对象。构造函数不能声明带const。
类的设计初衷是数据抽象和封装(data abstraction and encapsulation),类的使用者只需知道相应的接口。
类的声明(declaration)如 class myclass;声明myclass 是一种类类型,这时在当前文件中myclass是一种不完整类型(incomplete type),我们只能在函数参数或返回值定义myclass类型的指针或引用,不能定义myclass的对象,因为编译器无法为myclass的对象分配内存大小。同理类myclass的数据成员可以有myclass类型的指针或引用,不能有其自身类型的对象。
类的成员函数可以像普通函数一样进行重载,但不能和普通函数之间进行重载。
mutable类型数据成员,永不是const,常成员函数可以修改该类型数据成员的值,mutable int mi;。
成员函数的参数列表和函数体都在类的作用域里面,但是返回值不在。例如
class myclass { public: typedef int myint; myint set(); private: myint i;
}; myint myclass::set() { } |
编译时倒数第三行syntax error before `::' token。
myclass::myint myclass set() 。
名字的向上查找(name lookup),顺序为该成员函数体内,类内,类外。顺序为向上查找,下面的例子可说明
typedef int money;
class test{
public:
money mine;
private:
typedef float money;
};
编译会报错,因为后面又修改了money的含义。
构造函数,特殊的成员函数,用于创建类对象时初始化其数据成员的值,构造函数的个数没有限制,可以将其重载。不要将构造函数声明为常成员函数,那样他将不能修改数据成员。
构造函数可以使用冒号后接初始化列表的形式,这和在构造函数其体内实现赋值是有区别的。类的数据成员全在创建对象时初始化(不管其是否会出现在构造函数体内的语句中),如果初始化列表没有为其赋值,则系统将其初始化为默认值。
class s12{ public: s12(int a=2):i(a){ cout<<"start s12 constructor\n"; cout<<"at beginning i is "<<i<<endl; i=3; }
~s12(){ cout<<"in s12 destructor and i= "<<i<<endl; } int i; int *p; }; |
int main(void){ s12 obj1; cout<<"obj1.i: "<<obj1.i<<endl; cout<<"end main\n"; } |
运行结果
start s12 constructor at beginning i is 2 obj1.i: 3 end main in s12 destructor and i= 3 |
可以看到,冒号后接的初始化列表是在创建对象的同时执行的,而构造函数体内的语句是在其后执行的,还有一点,对const数据成员只可用初始化列表赋初始值,不可在构造函数体内用赋值语句。
下面的程序可以说明,将类s12改成如下,第三行将冒号初始化列表注释;倒数第三行类成员i改为const int型。
class s12{ public: s12(int a=2)/*:i(a)*/{ cout<<"start s12 constructor\n"; cout<<"at beginning i is "<<i<<endl; i=3; }
~s12(){ cout<<"in s12 destructor and i= "<<i<<endl; } const int i; int *p; }; |
编译时报错“assignment of read-only data-member `s12::i'”,如果将第三行注释去掉,第六行整体注释,则不会有任何问题。
const data成员和reference data 成员必须使用初始化列表的方式进行初始化。初始化列表的初始化顺序是按照类中数据成员的声明顺序,不是在初始化列表中的出现顺序。
将类s12修改为含有两个整形数据成员,在初始化列表中i2写在前,i在后
class s12{ public: s12(int a=2):i2(a),i(i2){ cout<<"start s12 constructor\n"; //cout<<"at beginning i is "< }
~s12(){ cout<<"in s12 destructor and i= "<<i<<endl; } int i; int i2; };
|
编译时会有警告:
warning: member initializers for `int s12::i2'
warning: and `int s12::i'
warning: will be re-ordered to match declaration order
运行时会先以i2的值初始化i,再以a的值初始化i2。
阅读(1599) | 评论(0) | 转发(0) |