C++ Primer Chapter7 类

第七章 类

声明:
本文为《C++ Primer 中文版(第五版)》学习笔记。
原书更为详细,本文仅作学习交流使用,未经授权禁止转载。

在公众号【Jacen的技术笔记】,回复 C++,即可获得 两万字C++ Primer 要点整理PDF。

P228-P273

类的基本思想是数据抽象和封装。

抽象是一种依赖于接口和实现分离的编程技术。

封装实现了类的接口和实现的分离。

7.1 定义抽象数据类型

(1)this

任何对类成员的直接访问都被看作this的隐式引用。

std::string isbn() const {return bookNo;}

等价于

std::string isbn() const {return this->bookNo;}

(2)在类的外部定义成员函数

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

double Sales_data::avg_price() const {
    if (units_sol)
        return revenue/units_sols;
    else
        return 0;
}

(3)构造函数

定义:类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫做构造函数。

构造函数没有返回类型;

构造函数的名字和类名相同。

类通过一个特殊的构造函数来控制默认初始化过程,这个函数叫做默认构造函数

编译器创建的构造函数被称为合成的默认构造函数

::: tip

只有当类没有声明任何构造函数的时,编译器才会自动的生成默认构造函数。

一旦我们定义了一些其他的构造函数,除非我们再定义一个默认的构造函数,否则类将没有默认构造函数

:::

7.2 访问控制与封装

(1)访问控制

说明符 用途
public 使用public定义的成员,在整个程序内可被访问,public成员定义类的接口。
private 使用private定义的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private部分封装了类的实现细节。

(2)友元

类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数成为它的友元。

以friend关键字标识。

友元不是类的成员,不受访问控制级别的约束。

::: tip

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

:::

// Sales_data.h

class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
}

// nonmember Sales_data interface functions
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);

//Sales_data.cpp

Sales_data 
add(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data sum = lhs;  // copy data members from lhs into sum
    sum.combine(rhs);      // add data members from rhs into sum
    return sum;
}

// transactions contain ISBN, number of copies sold, and sales price
istream&
read(istream &is, Sales_data &item)
{
    double price = 0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream&
print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " 
       << item.revenue << " " << item.avg_price();
    return os;
}

7.3 类的其他特性

(1)重载成员变量

Screen myScrren;
char ch = myScreen.get();
ch = myScreen.get(0,0);

(2)类数据成员的初始化

类内初始值必须使用=或者{}的初始化形式。

class Window_mgr{
private:
    std::vector<Screen> screens{Screen(24, 80, ' ')};
}

(3)基于const的重载

class Screen {
public:
    // display overloaded on whether the object is const or not
    Screen &display(std::ostream &os) 
                  { do_display(os); return *this; }
    const Screen &display(std::ostream &os) const
                  { do_display(os); return *this; }
}

当某个对象调用display的时候,该对象是否是const决定了应该调用display的哪个版本。

(3)类类型

对于一个类来说,在我们创建他的对象之前该类必须被定义过,而不能仅被声明。

(4)友元

友元类

如果一个类指定了友元类,则友元类的成员函数可以访问此类包括非公有成员在内的所有成员。

class Screen {
    // Window_mgr的成员可以访问Screen类的私有部分
    friend class Window_mgr;
}

令成员函数作为友元

class Screen {
    // Window_mgr::clear必须在Screen类之前被声明
    friend void Window_mgr::clear(ScreenIndex);
}

7.3 类的其他特性

(1)重载成员变量

Screen myScrren;
char ch = myScreen.get();
ch = myScreen.get(0,0);

(2)类数据成员的初始化

类内初始值必须使用=或者{}的初始化形式。

class Window_mgr{
private:
    std::vector<Screen> screens{Screen(24, 80, ' ')};
}

(3)基于const的重载

class Screen {
public:
    // display overloaded on whether the object is const or not
    Screen &display(std::ostream &os) 
                  { do_display(os); return *this; }
    const Screen &display(std::ostream &os) const
                  { do_display(os); return *this; }
}

当某个对象调用display的时候,该对象是否是const决定了应该调用display的哪个版本。

(3)类类型

对于一个类来说,在我们创建他的对象之前该类必须被定义过,而不能仅被声明。

(4)友元

友元类

如果一个类指定了友元类,则友元类的成员函数可以访问此类包括非公有成员在内的所有成员。

class Screen {
    // Window_mgr的成员可以访问Screen类的私有部分
    friend class Window_mgr;
}

令成员函数作为友元

class Screen {
    // Window_mgr::clear必须在Screen类之前被声明
    friend void Window_mgr::clear(ScreenIndex);
}

7.4 类的作用域

一个类就是一个作用域。

7.5 构造函数再探

(1)构造函数的初始值有时必不可少

::: tip

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

:::

class ConstRef{
public:
    ConstRef (int i);
private:
    int i;
    const int ci;
    int &ri;
};

ConstRef:ConstRef(int ii) : i(ii), ci(ii), ri(i){  }

(2)成员初始化的顺序

成员初始化的顺序与它们在类定义中出现 的顺序一致。P259

(3)委托构造函数

使用它所述类的其他构造函数执行它自己的初始化过程。

(4)如果去抑制构造函数定义的隐式转换?

在类内声明构造函数的时候使用explicit关键字。

7.6 类的静态成员

(1)声明静态成员

在成员的声明之前加上关键词static。

类的静态成员存在于任何对象之外,对象中不包含任何与静态成员有关的数据。

(2)使用类的静态成员

double r;
r = Account::rate();

小结

类有两项基本能力:

一是数据数据抽象,即定义数据成员和函数成员的能力;

二是封装,即保护类的成员不被随意访问的能力。

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

推荐阅读更多精彩内容

  • 第7章 类 7.1 定义抽象数据类型 类的基本思想:数据抽象、封装。数据抽象:一种依赖于接口和实现分离的编程及设计...
    北冥有鱼wyh阅读 303评论 0 1
  • 3. 类设计者工具 3.1 拷贝控制 五种函数拷贝构造函数拷贝赋值运算符移动构造函数移动赋值运算符析构函数拷贝和移...
    王侦阅读 1,804评论 0 1
  • 成员函数一个名为this的额外隐式参数来访问调用它的那个对象。当我们调用一个成员函数时,编译器负责把对象的地址传递...
    梦中睡觉的巴子阅读 176评论 0 0
  • 类 类的基本思想是数据抽象和封装数据抽象是一种依赖于接口和实现分离的编程设计技术类的接口包括用户所能执行的操作类的...
    人间百色阅读 213评论 0 0
  • Hi!这里是山幺幺的c++ primer系列。写这个系列的初衷是,虽然在学校学习了c++,但总觉得对这门语言了解不...
    山幺幺阅读 301评论 0 1