定义抽象数据类型

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

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

成员函数必须在类的内部声明,但是函数体可以在类内也可以在类外定义。

this

成员函数通过 this 指针来访问调用它的那个对象,当调用一个成员函数时,用请求该函数的对象地址初始化 this

this 形参是隐式定义的,任何自定义名为 this 的参数或变量的行为都是违法的。

const 成员函数

C++ 允许把 const 关键字放在成员函数的参数列表之后,此时,紧跟在参数列表后面的 const 表示 this 是一个指向常量的指针,像这样使用 const 的成员函数被称为常量成员函数。

常量成员函数不能改变调用它的对象的内容。

类作用域和成员函数

编译器首先编译类成员的声明,之后才轮到成员函数体,所以成员函数体可以随意访问类中的其它成员而无须在意这些成员的出现顺序。

在类的外部定义成员函数

如果成员函数被声明成常量成员函数,那么它的定义必须在参数初始化列表之后明确指定const属性。

类外部定义的成员的名字必须包含它所属类的名字。

定义类相关的非成员函数

如果函数在概念上属于类但是不定义在类中,则一般应该与类声明的头文件在一个文件内,这种方式下,使用接口的任何部分都只需要引入一个文件。

构造函数

每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数称为构造函数。

  • 构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。
  • 构造函数的名字与类名相同,构造函数没有返回类型。
  • 一个类可以有多个构造函数。

合成的默认构造函数

类通过一个特殊的构造函数来控制默认初始化过程,这个函数叫作默认构造函数,默认构造函数无须任何实参。

如果类没有显示地定义构造函数,那么编译器就会为类提供一个隐式定义的默认构造函数。这个默认的构造函数又被称为合成的默认构造函数。这个合成的默认构造函数将按照如下规则初始化类的数据成员:

  • 如果存在类内的初始值,用它来初始化成员。
  • 否则,默认初始化该成员。

合成的默认构造函数只适合非常简单的类,对于一个普通的类来说,必须定义它自己的默认构造函数:

  • 只有当类没有声明任何构造函数时,编译器才会自动地生成默认构造函数。
  • 如果类内包含了内置类型或者复合类型,则只有当这些成员全部都被赋予了类内的初始值时,这个类才适合于使用合成的默认构造函数,否则用户在创建类的对象时就可能得到未初始化的值。
  • 有的编译器不能为某些类合成默认的构造函数。比如类中包含了一个其他类类型的成员且这个成员的类型没有默认构造函数,那么编译器将无法初始化该成员。

= default 的含义

C++11 新标准中,如果需要使用默认的行为,那么可以通过在参数列表后面加上= default 来要求编译器生成默认构造函数。

= default 既可以和声明一起出现在类内部,也可以作为定义出现在类的外部。和其它函数一样,如果 = default 在类的内部,则默认构造函数是内联的;如果它在类的外部,则该成员默认情况下不是内联的。

构造函数初始值列表

Sales_data(const std::string &s,unsigned n,double p):
bookNo(s),units_sold(n),revenue(p*n)

构造函数初始值列表负责为新创建的对象的一个或几个数据成员赋值。

构造函数不应该轻易覆盖掉类内的初始值,除非新赋的值与原值不同。

如果不能使用类内初始值,则所有构造函数都应该显示地初始化每个内置类型的成员。

拷贝、赋值和析构

除了定义类的对象如何初始化之外,类还需要控制拷贝、赋值和销毁对象时发生的行为。

  • 初始化变量以及以值的方式传递或返回一个对象时将发生拷贝。
  • 当使用赋值运算符时会发生对象的赋值操作。
  • 当对象不存在时执行销毁操作。

如果不主动定义这些操作,编译器会默认合成一个版本,编译器生成的版本将对对象的每个成员执行拷贝、赋值和销毁操作。

某些类不能依赖于合成的版本

当类需要分配类对象以外的资源时,合成版本的操作将会失效。

许多需要动态内存的类可以也应该使用 vector 对象或者 string 对象来管理必要的存储空间,使用 vectorstring 的类能避免分配和释放内存带来的复杂性。

如果类包含 vector 或者 string 成员,则其拷贝、赋值和销毁的合成版本能够正常工作。

原文地址:https://www.cnblogs.com/xiaojianliu/p/12497752.html