(Boolan) C++面向对象编程(上) 第三周笔记

本周内容算是Part1的收尾了,通过这三周的课程会对面向对象编程这个概念有了更为深刻的理解,信息量有些大,可能还需要之后再复习。

  1. 首先是OOP里面对于class这个概念的延伸,主要讲了三种class之间的关系,有的教材上将类与类之间的关系讲的像人生哲学一样,但是只要理解这三种关系就能继续之后的系列课程。

对象之间的关系可以概括为继承(Inheritance)、组合(Composition)和代理(Delegation)3种。

7086751-c535ae8da544ed30.png
  • Composition组合, 表示has-a, 一个class里面完整包含另一个class

Composition概念早就存在,在c语言的struct中,使用了别的struct或者string等,都是组合(c语言实现面向对象就是用了这个特性)。

举例来说,queue中含有deque,即queue和deque是复合关系。(即只要A含有B,则就是一种复合关系)。但看代码,queue中的功能,都由dequeue完成。Dequeu的功能比较强大,就比较特殊了,成为一种adapter模式。

185929-83fb1071c78c3838.png

composition的构造是由内而外的:B的构造函数会首先调用A的默认构造函数(编译器自己调用,如果需要传递参数,需要在初始化列表显示调用),然后在调用自己的构造函数

Conainter::Container():: Component() {…} //编译器会自己去构造Component对象

container的构造函数首先调用component的default构造函数

composition的析构是由外而内的:B的析构函数首先执行自己的,然后才调用A的析构函数。Container的析构先调用自己,然后再调用Component的析构函数(编译器帮助完成,我们只要管理好Container的构造和析构就可以)。

如果Component的构造函数有多个,则需要显式的调用构造函数。

  • Delegation委托,Composition by reference

Tips:复合是两者生命一起出现,委托(又称Composition by reference)Container先创建起来,等到需要Component的时候,才创建Component,即不同步。

a.设计模式:Handle/Body(pointer to implementation:我有一个指针,去指向为我实现所有功能的那一个类。——指针可以指向不同的实现类,所以又称编译防火墙:(下图)左边的永远不用再编译,要编译的只是(下图)右边的。

185929-83fb1071c78c3838.png

b.共享

如上图红圈所示,a,b,c三个指针指向同一个字符串,即共享一个字符串,这样的好处是节省内存空间(当然,共享的内容必须完全一样),但是需要注意,当想改变一个指针指向的内容时,其余两个指针指向的值也就随之改变,也就是牵一发而动全身。

  • Inheritance,类的继承,是新的类从已有类那里得到已有的特性。或从已有类产生新类的过程就是类的派生。原有的类称为基类或父类,产生的新类称为派生类或子类。
    Inheritance的声明:
    class 派生类名:继承方式 基类名1, 继承方式 基类名2,...,继承方式 基类名n
{

subclass成员声明;

};
  • 一个派生类可以同时有多个基类,这种情况称为多重继承,派生类只有一个基类,称为单继承。直接派生,间接派生。
  • 继承方式规定了如何访问基类继承的成员。继承方式有public, private, protected。如果不显示给出继承方式,默认为private继承。继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。
  • 派生类继承基类中除构造和析构函数以外的所有成员。
  • 派生类生成:
    吸收基类成员(除构造析构函数以外的所有成员);
    改造基类成员(根据继承方式调整基类成员的访问,函数在子类中的覆盖,以及虚函数在子类中的覆盖)

Tips:C++类的3种继承方式,分别是public继承,protected继承,private继承。

最常用的还是public继承。class默认的是private继承,它的member如果没写权限也是默认.
3个继承权限的区别:

class ex0

{

private:

void showPrivate(){cout<<"this is private function!";}

public:

void showPublic(){cout<<"this is public function!";}

protected:

void showProtected(){cout<<"this is protected function!";}

};

class ex1:public ex0

{

public:

void func()

{

showPrivate();

//错误因为此函数访问权限只有基类 ex0 自己有

showPublic();

showProtected();

}

};

class ex2:protected ex0

{

public:

void func()

{

showPrivate();

//错误因为此函数访问权限只有基类 ex0 自己有

showPublic();

//正确, 但是此函数由于 ex2 的保护继承这个函数的访问权限已经变成了 protected,

//也就是说对于外部类来说已经不具备访问这个函数的权限了

showProtected();

}

};

class ex3:private ex0

{

public:

void func()

{

showPrivate();

//错误因为此函数访问权限只有基类 ex0 自己有

showPublic();

//正确, 但是此函数由于 ex3 的私有继承这个函数的访问权限已经变成了 private,

//也就是说对于外部类和派生类来说已经不具备访问这个函数的权限了

showProtected();

//正确, 但是此函数由于 ex3 的私有继承这个函数的访问权限已经变成了 private,

//也就是说对于外部类和派生类来说已经不具备访问这个函数的权限了

}

};

  1. Inheritance(继承)with virtual functions

继承搭配着虚函数。

子类可以继承父类的所有内容,包括数据和函数。从内存角度,可以继承数据;对于函数,不能从内存角度理解,而是子类继承了父类的函数调用权。

函数分为三种情况:

  • non virtual function:你不希望derived class重新定义override
  • virtual function:希望derived class的重新定义override。已有默认定义。
  • pure virtual:你希望derived class一定要重新定义。没有默认定义。

虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。
在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了 这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

假设有下面这个类:

class Base {
public:
    virtual void f( ) { cout << "Base::f" << endl; }
    virtual void g( ) { cout << "Base::g" << endl; }
    virtual void h( ) { cout << "Base::h" << endl; }
};

我们可以通过Base的实例来得到虚函数表。

    Base b;
    cout << "虚函数表地址:" << (int*)(&b) << endl;
    cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;

可得到:

虚函数表地址:0012FED4
虚函数表 — 第一个函数地址:0044F148
  1. 设计模式:Prototype(原型模式)
    用原型实例制定创建对象的种类,并且通过拷贝创建新的对象;

类图:

5665430-1f227b1e63bb9b76.jpg

核心是克隆函数的运用
组成元素:
Prototype:声明克隆自身的接口;
ConcretePrototype:实现克隆自身的操作;

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

推荐阅读更多精彩内容