GeekBand C++面向对象高级编程(上) 笔记&心得 2(1)

7.三大构造函数:拷贝构造,拷贝赋值,析构函数

Class With Pointer member(s) :要写析构函数,而析构函数主要的作用就是删除新建的内存空间,删除不再使用的指针指向的不再使用的Object

String类讲解代码的Part:

String(const char* cstr=0);             //构造函数,默认将cstr的初始值赋为0

String(const String& str);                //拷贝构造,将参数str的m_data拷贝。深拷贝,自己创建一块内   存空间将str的m_data重新拷贝一份。因为它是接受自己(String)这种东西,所以是拷贝构造

String& operator=(const String& str);  // 拷贝赋值。

~String();

char* get_c_str() const { return m_data; }

Q:为什么我需要重新写拷贝构造和拷贝赋值??

A:因为编译器使用的默认的拷贝构造和拷贝赋值是使用值的,而不知指针的。所以当我们使用带指针的时候一定要自己写拷贝构造和拷贝赋值。

Q:拷贝构造函数    VS   拷贝赋值函数   两者有什么区别??

A:拷贝构造函数是新建一块内存空间来存放新的内容。也就是值拷贝。拷贝的是内容。

      拷贝赋值函数是拷贝的地址。也就是位拷贝。当其中一个对象修改的时候另外的一个也会随之变化。

       第二个例子就是使用编译器默认的拷贝赋值,可以看到发生了内存泄露。

使用默认的拷贝赋值会发生的危险

  这里有个相关内容的BLOG地址:http://www.cnblogs.com/kaituorensheng/p/3245522.html

来看看拷贝赋值函数的编写:

拷贝赋值函数的编写

8.堆,栈与内存管理

8.1      堆  栈

堆和栈的定义

堆必须使用new来动态分配内存,使用delete删除。

栈是比较小的,如果什么东西都使用栈来存储可能会发生爆栈的情况。例如:



在全局变量中声明,使用堆来存储


在局部变量中声明,使用栈来存储

在第一种情况中内存发生了溢出而中止了程序,第二种情况则正常编译成功。

说明使用堆相比于使用栈不那么容易发生溢出,它取决于你内存的大小。

8.2      static  object     global object   heap object

static object静态对象在函数作用域执行完之后仍然存在于程序中没有被销毁,直到程序执行完之后才消失。

global object是全局对象,到程序执行完之后才消失。

Q:两者有什么区别??

A:区别在于global object更早地被创建(在程序的一开始),而静态对象则是在执行到指定的语句的时候才被创建。

heap object是堆对象,它和上面两个没有那么像。其生命周期是在new创建时开始,在delete删除时结束。记住new后必须delete删除,否则会发生内存泄露。

8.3编译器如何创建删除对象的





可以知道,构造函数是从外而内构造的,而析构函数是从内而外析构的。

Q:为什么array new 要对于 array delete

A:


这张图可以知道如果使用delete只能删除一个dtor,而使用array delete才能删除三个dtor。这样才不会发生内存泄露。

10. 补充拓展:类模板,函数模板以及其他



函数是如何如何处理到不同的对象的

从图中可以看到,通过this指针来指向不同的对象来告诉函数要处理什么对象数据。

静态函数:静态函数没有this pointer,所以静态函数只能处理静态数据

Q:静态函数什么时候用?好处有什么?

A:不用实例化;      被预编译;      访问速度比较快。

http://www.cnblogs.com/devinzhang/archive/2012/04/27/2473570.html

举个栗子:


静态对象的声明定义

可以看到,在类外一定要加上double Account::m_rate = 8.0;

Singleton设计模式:

使用静态实现的设计模式。非常有意思。来看看代码:


Singleton较差的实现


singleton较好的实现

Singleton设计模式将类的实例化使用static完成并如果调用只调用一次。
下面摘抄百度知道的一个回答:

static关键字至少有下列作用:

(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问。

(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

上面(较差)和下面(较好)的区别在于一个把static A a放在private区,另一个放在了getInstance()区。为什么放在getInstance区叫好呢? 因为如果放在private区不论如何都被创建了,而放在getInstance()区只有在调用getInstance()的时候在被创建。这样使得程序的执行有更高的效率。

模板:

模板涉及比较浅不细说。


类模板


函数模板

命名空间:

比较浅不细说。


命名空间的使用

11.组合与继承

举个课件里的栗子:

类的组合



类的组合2

可以看到queue中包含了deque,而deque中又包含了Itr,这就是一次类的组合(Composition)。

下面再来介绍一个特性:委托(Delegation)

依旧是课件:


委托(Delegation)

Q:什么使用用组合什么时候用继承呢?

A:优先使用对象组合,而不是类继承

Q:委托和组合有什么区别呢?

A:从课件中可以看到,委托其实就是Composition by Reference(学术界只说by reference不说by pointer。。。。so。。。。)。使用引用的组合。委托是对一个类的功能进行扩展和复用的方法。它的做法是:写一个附加的类提供附加的功能,并使用原来的类的实例提供原有的功能。扩展和复用一个类的功能常用的一种方法是继承,而另一种更普遍的方法则是委托。在很多情况下委托很适用,而继承则并不适用。


pimpl(Handle/Body)实现方法:图左边(String.hpp)提供一个借口,而具体实现方式在(String.cpp)的实现方法就叫做pimpl。又叫做编译防火墙(左边不用编译只要编译右边)。

继承(Inheritance):



继承的使用方法(黄色部分)



继承下的构造和析构



继承下的构造和析构还是特别容易理解,不细说。

虚函数:


虚函数的分类

Q:侯老师留的一个小问题,Derived是Base的子类,又和Component组合,而Base和Component之间没有任何关系,探究这样子的一个结构中构造函数和析构函数的调用顺序



留下的小问题的程序结构

A:下面是我的答案:



这里是代码


这里是答案

可以看到编译器先构造了Base,然后构造了Component,最后才构造了Derived。紧接着最先析构了Derived,接着析构了Component,最后析构了Base。我们可以知道编译器首先构造父类的对象,接着构造了组合类的对象,最后才构造了自己。而这也是合乎逻辑的。


而另一个问题:


问题

这个问题很明白,从内而外构造是Component,Base,Derived。而析构时相反顺序的。



答案

委托+继承的方法(最强大的!):

举个栗子:

观察者设计模式

观察者模式资料:

http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html

http://lavasoft.blog.51cto.com/62575/201617/

Prototype设计模式:

创建一个未来的对象。

说明: #(protected)   -(private)   下划线(静态)  没有标记=(+)也就是公有的

代码:


Prototype框架图


代码1


代码2


代码3

简单说就是通过复制一份已经存在的实例来建立一个新的实例(未来的实例)。原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。

http://blog.csdn.net/hguisu/article/details/7518947

总结一下:

了解到的方法:

1.Adapter


Adapter

2.Handle/Body

Handle/Body(pImpl)

3.Template Method


Template Method

4.Observer


Observer

5.Prototype


Prototype

几种面向对象的方法:

复合  继承   委托   继承+委托     继承+虚函数


以上。

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

推荐阅读更多精彩内容