我读C++ Primer - 类

来源:互联网 发布:汽车美容会员软件 编辑:程序博客网 时间:2024/04/28 06:24

类是C++ 最基本的特性。类允许我们为自己的应用定义新类型,从而使得程序更加简洁且易于修改。

类的基本思想是数据抽象封装。数据抽象是一种依赖于接口和实现分离的编程技术。封装实现了接口与实现的分离。


1  定义类

定义在类内部的函数是隐式的inline 函数。

成员函数通过一个名为this 的额外的隐式参数来访问调用它的那个对象。

常量对象,以及常量对象的引用或指针都只能调用常量成员函数。

类的作者常常需要一些辅助函数,尽管这些函数定义的操作从概念上来说是属于类的接口的组成部分,但他们不属于类本身,可以声明为friend 函数。

构造函数:类通过一个或几个特殊的函数来控制其对象的初始化过程。无论何时只要类的对象被创建,就会执行构造函数。

如果自己没有定义构造函数,编译器会给我们生成一个默认构造函数。而一旦自己声明了任何一个构造函数,都不会有默认构造函数。

合成的默认构造函数的初始化成员规则:如果类内有初始值,用它来初始化成员,否则,默认初始化该成员。遇到复合类型其值为未定义。合成的默认构造函数只适合非常简单的类,因此最好自己声明一个默认构造函数。

Sales_data() = default;
表示我们既需要其他形式构造函数,也需要默认构造函数,此时,编译器会生成一个默认构造函数。

Sales_data(const string& s,unsigned n) : bookNo(s), units_sold(n){}
新出现的部分是构造函数初始化列表。
其他重要的如拷贝,赋值和析构,如果我们没有定义,编译器会合成一个版本。但是当类需要分配类对象之外的资源是,常常会失效,所以最好自己定义这些函数。


2  访问控制

类与结构体的区别是,struct 中,定义在第一个访问说明符之前的成员是public, class相反,是private。

友元:类可以允许其他类或者函数访问它的非公有成员,就是令其他类或函数成为它的友元。友元不是类的成员,所以不受所在区域的访问限制的约束。一般来说,最好在类定义开始或者结束前的位置集中声明友元。

友元的声明仅仅指定了访问的权限,而不是普通意义上的函数声明,必须在友元声明之外再专门对函数进行一次声明。

封装的好处:确保用户代码不会无意间破坏封装对象的状态;被封装的类的具体实现细节可以随时改变,无需调整用户级别的代码。

3  类的其他特性

内联函数:建议在函数声明和定义的地方都说明inline。

可变数据成员:可以修改类的数据成员,不管是不是在const 成员函数内。定义前加 mutable 关键字。

设计良好的C++ 代码常常包含大量类似于 “do_display” 的小函数,通过调用这些函数,可以完成一组其他函数的实际工作。

友元:除了友元函数,还可以声明友元类。注意:友元关系不存在传递性。友元函数使用之前必须在外部声明。


4  类的作用域

每个类都会定义自己的作用域。作用域外,普通的数据和函数成员只能由对象,引用或者指针使用成员访问运算符来访问,类类型成员通过作用域运算符访问。

类型名的定义(如 typedef) 通常出现在类的开始处,这样就能确保所有使用该类型的成员都出现在类名的定义之后。


5  构造函数再探

如果没有在构造函数的初始化列表中显式的初始化成员,则该成员将在构造函数体之前执行默认初始化。这会影响效率。

如果成员是const,引用,或者某种未提供默认构造函数的类类型,必须通过构造函数初始化列表为这些成员提供初值。

初始化的顺序与在类定义中出现的顺序一致。

C++ 11 新加了委托构造函数。一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,如:

Sales_data(const string& s,unsigned n) : bookNo(s), units_sold(n){}Sales_data() : Sales_data("",0) {} 
如果构造函数只接受一个实参,它实际上定义了转换为此类类型的隐式转换机制。编译器只会自动的执行一步类型转换。

防止类型转换要在构造函数声明前加上explicit。在类外定义时不能重复加此关键字。

explicit 构造函数只能用于直接初始化,不能用于拷贝初始化,如:

Sales_data item1(null_book);   //直接初始化sales_data item2 = null_book; //错误,拷贝初始化


6  类的静态成员

类的static 静态成员只与类本身直接相关,而不是与类的各个对象保持关联。

类静态函数不能声明成 const 的,不包含this 指针。

可以通过类的对象,引用或者指针来访问静态成员,成员函数不用通过作用域运算符就能直接使用静态成员。

在类的外部定义静态成员时,static 不能重复出现。

静态数据成员不属于任何对象,所以不能由类构造函数初始化,也不能在类内部初始化,必须在类的外部定义和初始化静态成员。只能定义一次,可以把静态数据成员的定义与其他非内联函数的定义放在同一个文件中。

静态数据成员是不完全类型,其类型可以是它所属类的类型,而非静态数据成员则受到限制,只能声明成它所属类的指针或引用。另一个区别是,可以使用静态数据成员作为默认实参。



0 0
原创粉丝点击