Chinaunix首页 | 论坛 | 博客
  • 博客访问: 289709
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: C/C++

2008-07-19 22:14:08

 
上一篇未完的等看完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。

阅读(1568) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~