c++ Primer 之 类的初始化,赋值和析构

类别:编程语言 点击:0 评论:0 推荐:

14.1 类的初始化

型如下面这样的类:

Class data

{

Public:

       int inval;

       char* ptr;

};

可用如下方式初始化,而不需要提供构造函数:

Data local1 = {0, 0}; //称为 显式初始化表

 

这是因为其数据成员都是公有的。

对于大多数类而言,提供一个构造函数初始化数据成员是一个好的选择。但是上面的初始化形式在 初始化大型数据结构,如调色板类 时尤其有用,可节省构造函数调用开销。

 

14.2 类的构造函数

构造函数与类同名,不可指定返回类型。

构造函数可以有多个,但参数表必须唯一。

使用new时,只有当成功得到了内存,编译器才会调用类构造函数。

只有当没有构造函数或者定义了缺省构造函数时,我们才可以不指定实参集来定义类对象。 在实践中,如果定义了其他构造函数,则建议提供一个缺省构造函数。

构造函数不能是const或者是volatile。

在缺省情况下,单参数构造函数被用作转换操作符。使用关键字Explicit可以抑制无意的隐士转换。

例:

Extern void print(Account& acct);

Int main()

{

       Print(“oos”); //Account构造函数被隐式调用

}

 

14.2.1 缺省构造函数

缺省构造函数是指不需要用户指定实参就能够被调用的构造函数。这并不意味着它不能接受实参,如:iStack::iStack(int iSize = 0) 是一个缺省构造函数。

如果类数据成员都是公有的,并且没有用户定义的构造函数,则类对象的成员初始化值取决于上下文环境。如果为静态对象,则可保证成员初始值为0.如为局部定义或者是动态分配的对象,则初始值为随机。

如果不存在缺省构造函数,编译器不一定会生成一个。

(在<深度探索c++对象模型>一书中提到,在以下四种情况下编译器将提供一个为一个类提供缺省构造函数:

1.       其基类有缺省构造函数;

2.       其对象成员有缺省构造函数;

3.       其拥有虚函数;

4.       其拥有虚基类)

 

14.2.2 限制对象创建

将构造函数非公有化。这样做的好处是:

防止将一个类的对象向该类另一个对象拷贝;

指出只有当该类作为基类,而不能被应用程序直接调用时,构造函数才能被调用。

 

14.2.3 拷贝构造函数

将相同类的不同对象相互赋值,缺省方式是按成员初始化。当存在指针成员时,显然不合适,此时需要提供拷贝构造函数。

拷贝构造函数拥有一个指向类对象的引用作为参数。

 

14.3 类的析购函数

析构函数是一个特殊的由用户提供的函数,当该类的对象离开了它的作用域,或者delete操作应用到该类的对象指针时,会被自动调用。

当一个类的数据成员按值存储时,不需要析构函数,(如:float x, y, z).

C++语言内部保证,不会delete一个不指向任何对象的指针。

 

14.3.1 显示的析构调用

 

14.4 类对象数组

型如这样定义:Account table[3] = {“A”, //调用单参数构造函数

                                                        Account(“B”, 10.00) //调用多参数构造函数

                                                        //第三个元素不指定,则调用缺省构造函数(如果存在的话)

                                                        }

 

14.5 成员初始化表

不存在从String类到char*的隐式转换,但String类支持从char*转换到String。

通过成员初始化表,类数据成员可以被显式初始化。

构造函数的执行被分为两个阶段:隐式或者显式初始化阶段;计算执行阶段,由构造函数体内所有语句构成。

不存在成员初始化列表时,初始化是隐式的,基类以及所有成员类对象的缺省构造函数将被调用。

除了const和引用数据成员之外(这两种只能使用成员初始化表),使用初始化列表和使用赋值语句的结果和性能是等价的。

初始化顺序与类成员对象被声明的顺序相对应,而与初始化列表顺序无关。

初始化列表中的成员的初始化总是先于构造函数体内被赋值的成员。为了避免错误,通常建议将一个成员初始化另一个成员的赋值动作放在构造函数体内。

 

14.6 按成员初始化

用一个类对象初始化另一个类对象,如:

1.       用一个类对象显式初始化另一个类对象: Account NewAccount(OldAccount);

2.       将一个类对象作为实参传递给一个函数:Extern A(Account account); if (A(OldAccount)

3.       将一个类对象作为一个函数的返回值传递回来。

4.       非空顺序容器的定义

缺省的是按成员初始化,无论是否存在显式构造函数。

此时容易发生指针“别名”问题。可以通过提供一个显示拷贝构造函数解决。另外也可以通过以下替代方案,禁止按成员初始化:

1.       声明一个private的拷贝构造函数,这样可以防止按成员初始化出现在 除成员函数和友元函数以外的 其它任何地方;

2.       不提供该函数的定义。编译通过但产生连接错误。

 

14.6.1 成员类对象的初始化

如果一个类提供了一个显式拷贝构造函数,则调用该函数进行初始化,否则缺省按成员初始化

 

14.7 按成员赋值

类似于按成员初始化。

 

14.8 效率问题

NLV优化,见 深度探索c++对象模型。

所以,尽量使用如下语句:

Matrix c = a + b;

而不是:

Matrix c;

C = a + b;

 

本文地址:http://com.8s8s.com/it/it23537.htm