第七章 类

7.0 前言

  1. 类的基本思想: 数据抽象(data abstraction)封装(encapsulation)
  2. 数据抽象:是一种依赖于 接口(interface)实现(implementation) 分离的编程(以及设计)技术。
  3. 类的接口: 包含了用户所能执行的操作。
  4. 类的实现: 包含了类的数据成员,负责接口实现的函数体以及定义类所需的各种私有函数。
  5. 封装: 实现了类的接口和实现的分离,隐藏了类的实现细节,使得用户只能使用类的接口而无法查看其实现细节。

7.1 定义抽象数据类型

  1. 成员函数(member function): 声明写在类定义内部的函数,而定义写在类内外都可以。但是写在类定义外的函数名前必须加上类名。
    例如:
class Stu
{
  public :
  void display( );
  //内部定义成员函数
  void show( ){
  }
  Stu& ret();
  private:
  string name;
  unsigned age;
};
//外部定义成员函数
//注意在函数前要添加 类名:: 
void Stu::display( )
{
  cout << " name: " << name << " age: " << age;
}
  1. 运算程序的人称为用户(user),而使用别人定义的自定义类的程序员其实也是用户。
  2. 注意:成员函数默认都是隐式的内联(inline)函数。
  3. 当我们调用成员函数时,实际上是在替某个对象调用它。成员函数通过一个关键字 this ,同时也是 所有成员函数的隐式参数 来访问调用它的那个对象。 当我们调用一个成员函数时,用请求该函数的对象地址初始化 this 。
    例如调用上例成员函数 display 。
Stu Stu1;//定义一个 Stu1 对象
display();

则编译器负责将 Stu1 的地址传递给 display 的隐藏形参 this ,可以等价地理解为编译器将该调用重写成了如下形式:

display(&Stu1);//其中的 name 和 age 可以理解成写成了 Stu1.name 和 Stu1.age 
  1. this 关键字: 通常用于访问对象,而不是单访问对象的某个成员

① this 是 隐式定义 的;
默认情况下, this 是一个指向当前对象常量指针,它的类型是指向非常量版本 class 类型的常量指针 (是 top-level const ,但不是 low-level const );
但是在成员函数的参数列表后面添加 const ,则可以修改 this 的类型为指向常量版本 class 类型的常量指针 (既是 top-level const ,也是 low-level const )。

  1. 常量成员函数(const member function): 在参数列表后添加 const 的成员函数。
  2. 编译器分两步处理 class 类型:

①首先编译成员的声明;
②然后才编译成员函数体。

  1. 由第 7 点可知道, 成员函数体可以随意使用类中的其他成员而无需在意这些成员出现的次序
  2. 与其他函数一样,在类定义外定义的成员函数时,成员函数的函数头必须与类定义内的函数声明包含相同的返回类型、参数列表、函数名,同时还要在函数名前添加 类名:: (这是为了告诉编译器该方法是属于类定义的作用域内的)。另外,常量成员函数还要在参数列表后面添加 const 关键字。
  3. 常量对象,以及常量对象的引用和指针都只能调用常量成员函数。
  4. 定义一个返回 this 指向的对象的函数,例如:
Stu& Stu::ret()
{
  return *this;  //返回调用该函数的对象
}
  1. 一般来说,如果非成员函数是类接口的组成部分(概念上属于类但实际上并不是成员函数),则这些函数的声明应该与类在同一个头文件内。
  2. 默认情况下,拷贝类的对象其实是拷贝该对象的数据成员。
  3. 构造函数(constructor): 类用于初始化对象的成员函数。
  4. 构造函数具有以下特点:
  1. 没有返回类型;
  2. 函数名与类名相同;
  3. 与其它函数一样具有一个参数列表和函数体(两者可能为空);
  4. 可以有多个;
  5. 不能被声明成常量成员函数。
class CExample {
public:
    int a;
    float b;
    CExample()
    {
        a=0;
        b=8.8;
    }
};
  1. 默认构造函数(default constructor): 实现对象的默认初始化的特殊构造函数,默认构造函数 没有形参 ,当类 对象创建时自动执行
  2. 只有当程序员的类没有显式定义构造函数,编译器才会自动为其隐式定义一个默认构造函数。一旦定义了类的构造函数,则编译器不会自动为其定义默认构造函数。此时需要程序员自己定义默认构造函数。
  3. 合成的默认构造函数(synthesized default constructor): 编译器定义的构造函数。
  4. 对于绝大多数类,这个合成的默认构造函数将按照如下规则初始化类的数据成员:
  • 如果类内成员变量存在了初始值,则用他来初始化成员变量
  • 否则,默认初始化该成员
  1. 所以, 编译器有时候不能为某些类定义默认的构造函数 。比如当类中某些成员的类型没有默认构造函数,此时编译器将无法初始化该成员。
  2. 构造函数初始值列表(constructor initialize list)冒号以及冒号和花括号之间的代码 ,用于为新创建的对象的一个或几个数据成员赋初值。构造函数初始值是成员变量名字的一个列表,每个名字后面紧跟着括号括起来的(或者在花括号内的)成员初始值。不同成员的初始化通过逗号分隔开。
    例如,下面的构造函数与上面的构造函数的结果是相同的。
class CExample {
public:
    int a;
    float b;
    //构造函数初始化列表
    CExample(): a(0),b(8.8)
    {}  //因为构造函数只是为了初始化类成员,所以这里的函数体为空
};
  1. 如果构造函数存在没有被显式初始化的类成员,则这些类成员将会被默认初始化。
  2. 注意: C++ 初始化类成员时,是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。
  3. 同样的,构造函数也可以在类外部定义,也要在构造函数名前添加 类名::
  4. 一般来说如果我们不主动定义,编译器将会对类的每个成员合成初始化、拷贝、赋值和销毁操作。 只是对于某些类来说合成的操作无法正常执行,比如管理动态内存的类通常不能依赖于上述合成的操作,但是如果管理动态内存的类使用的是 vector 或 string 则编译器合成的操作可以正常执行。

7.2 访问控制与封装

7.3 类的其他特性

7.4 类的作用域

7.5 构造函数再探

7.6 类的静态成员

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,495评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,469评论 2 369
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 140,825评论 0 318
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 51,974评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,849评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 45,990评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,415评论 3 380
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,125评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,351评论 1 288
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,474评论 2 307
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,249评论 1 324
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,119评论 3 310
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,496评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,838评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,118评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,366评论 2 340
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,573评论 2 335

推荐阅读更多精彩内容

  • 简介 类的基本思想是数据抽象data abstraction和封装encapsulation。数据抽象是一种依赖于...
    TOMOCAT阅读 410评论 0 1
  • Hi!这里是山幺幺的c++ primer系列。写这个系列的初衷是,虽然在学校学习了c++,但总觉得对这门语言了解不...
    山幺幺阅读 288评论 0 1
  • 类的基本思想是数据抽象和封装。数据抽象是一种依赖于接口和实现分离的编程技术。 类的接口:用户所能执行的操作。 类的...
    丶不霁何虹阅读 721评论 0 2
  • 1.技巧化对象:定义类,然后使用new来创建这个类的技巧。2.定义对象构造器:定义一个名为__construct(...
    天黑北风吹阅读 224评论 0 0
  • 8.1 创建个使用类 8.1.1 创建一个Dog类 1. 方法init() —— 类似于java...
    永不熄灭的火焰_e306阅读 160评论 0 0