摘要: C++的对象模型就是C++的对象在内存中是如何排布的。 C++的对象就包含了成员变量和成员函数。 回归本质: class和struct遵循相同的内存对齐规则,因此计算class占用的内存大小和struct一样。 值得思考的问题: 对象内存布局初探: 可以看出打印的都是20。 增加成员函数: 第40行 阅读全文
posted @ 2018-09-02 22:31 周伯通789 阅读(228) 评论(0) 推荐(0)
摘要: 上一节中,函数重写遇上赋值兼容出现了问题: 34、35行调用的都是父类中的print函数。 35行我们给的实参是Child对象,期望调用子类中的print函数,但是运行结果并不是这样。 函数重写回顾: 子类中重定义父类中已有的函数,就是因为父类中的函数满足不了我们的需求。 我们期望的是只要是子类对象 阅读全文
posted @ 2018-09-02 22:01 周伯通789 阅读(231) 评论(0) 推荐(0)
摘要: 父子间的赋值兼容: 子类对象兼容性实验: 第40行我们可以直接使用子类对象来初始化父类对象。这就是赋值兼容性。 47、48不会发生同名覆盖,因为rp本身就是父类类型的引用,只不过引用的对象是子类对象。47、48行会直接去父类中找add函数,所以不会报错。 51、52行同时找不到mv和带三个参数的函数 阅读全文
posted @ 2018-09-02 21:32 周伯通789 阅读(224) 评论(0) 推荐(0)
摘要: 思考: 同名成员变量: 图中的mi到底是子类的,还是从父类那里得到的? 父子间的冲突: 子类中的成员将隐藏父类中的同名成员,这叫同名覆盖。 是隐藏,是覆盖,而不是销毁,父类中的同名成员是依然存在的。我们通过作用域分辨符还是可以访问到的。 示例程序: 运行结果: 我们通过直接访问的方式访问的是子类中的 阅读全文
posted @ 2018-09-02 20:54 周伯通789 阅读(218) 评论(0) 推荐(0)
摘要: 思考: 如何初始化父类成员? 父类构造函数和子类构造函数有什么关系? 子类对象的构造: 子类构造函数对继承而来的成员进行初始化有两种方式: 1、直接通过初始化列表或者赋值的方式进行初始化 2、调用父类构造函数进行初始化 父类构造函数在子类中的调用方式: 显式调用只能在初始化列表进行。 如下: 示例程 阅读全文
posted @ 2018-09-02 18:41 周伯通789 阅读(192) 评论(0) 推荐(0)
摘要: 被忽视的细节: 问题: 示例: 可以看到其他两种继承方式也完全可以编译通过。 这三种不同的继承有什么区别呢? 不同的继承方式: 深度实践: 遗憾的事实: JAVA、C#就只有一种继承方式--公有继承。 小结: 阅读全文
posted @ 2018-09-02 18:27 周伯通789 阅读(175) 评论(0) 推荐(0)
摘要: 子类是否可以直接访问父类的私有成员? 思考过程: 示例: 可以看到27行在子类中直接访问父类的私有成员就报错了。 示例: 将mv的访问级别改为protected,编译就不会报错了。 结果如下: 上述程序中的第47行是错误的,因为mv是protedted的,而main函数是类的外部,不能直接访问。 思 阅读全文
posted @ 2018-09-02 17:23 周伯通789 阅读(418) 评论(0) 推荐(0)
摘要: 面向对象的高端课程都是和继承相关的,例如设计模式。 思考: 类与类之间是否存在直接的关联关系? 生活中的例子: 组合关系的程序描述: 运行结果如下: 组合关系的特点: 实际工程中先考虑组合关系。组合关系能满足需求就用组合关系。 继承关系: 示例: 子类继承了父类的mv和其他成员函数,所以打印出100 阅读全文
posted @ 2018-09-02 16:49 周伯通789 阅读(186) 评论(0) 推荐(0)
摘要: 问题: 类类型能否转换到普通类型? 示例如下: 可以看到上述程序中的强转是不成功的。 这时就需要引入新的语法规则了,类型转换函数: 添加类型转换函数: 运行结果如下: 分析: 上述程序中的int i = t相当于调用函数,int i = t.operator int()。 类类型之间相互转换: 示例 阅读全文
posted @ 2018-09-02 16:15 周伯通789 阅读(167) 评论(0) 推荐(0)
摘要: C语言编译中类型转换: C语言编译器只会在标准数据类型之间做转换。 隐式类型转换复习: 结果如下: 第26行的s和'b'转换为int类型再相加。 问题: 示例程序: 编译结果如下: 可以看到这种普通类型到类类型的强制转换是不被允许的。 将程序更改如下: 这时就可以正常编译通过了。 再论构造函数: 只 阅读全文
posted @ 2018-09-02 16:01 周伯通789 阅读(246) 评论(0) 推荐(0)
摘要: 值得思考的问题: 示例: 反汇编如下: 我们看到i++和++i对应的汇编是完全一样的。仅仅是寄存器不一样。 因为我们并没有使用这两行语句的返回值,而是单纯的两行i++和++i,所以编译器优化后,将返回值抛弃,因此它们的底层汇编是一样的。 linux下g++编译器的反汇编如下: 可以得到结论,独立的两 阅读全文
posted @ 2018-09-02 15:16 周伯通789 阅读(265) 评论(0) 推荐(0)
摘要: 逗号操作符: 我们如果重载逗号操作符,必须遵守上面的几点。特别是最后两点。 逗号操作符示例: 第35行等价于 j = 6。 重载逗号操作符: 重载逗号操作符要用全局函数。 示例程序: 我们将36行改成func调用的形式: 我们期望36行先计算func(t0),再计算func(t1),但是从输出结果可 阅读全文
posted @ 2018-09-02 14:49 周伯通789 阅读(208) 评论(0) 推荐(0)
摘要: 潜规则: 在C语言中并没有bool类型。C++中才有。 逻辑表达式示例: 添加func函数: 运行结果: 重载逻辑操作符: C++中允许重载逻辑与和逻辑或,重载逻辑操作符程序入下: 第42行我们期望只调用func(t0),但是从输出可以看到func(t1)也被调用了。而且先调用的是func(t1)。 阅读全文
posted @ 2018-09-02 14:27 周伯通789 阅读(180) 评论(0) 推荐(0)
摘要: 永恒的话题: 内存泄漏示例: 这段程序我们没有释放堆空间,造成了内存泄漏。 深度的思考: 一片堆空间最多只能由一个指针标识,这可以避免多次释放。杜绝指针运算和比较可以避免野指针。 C++中不存在这样的指针,我们需要自己实现。 解决方案: 这四条都是硬性规定,最后两条说的是同一个问题。 程序与运行结果 阅读全文
posted @ 2018-09-02 12:15 周伯通789 阅读(223) 评论(0) 推荐(0)
摘要: 关于赋值的疑问? 示例程序: 第22行是赋值操作符重载,返回值应该为引用类型,参数也应该为引用类型,否则容易出bug。 24行的判断为了避免自赋值。因为在C语言中,i = i这种自赋值是合法的,C++为了兼容C语言,t2 = t2这种自赋值也是合法的。 我们的数组类将拷贝构造定义为私有的,就是不允许 阅读全文
posted @ 2018-09-02 11:26 周伯通789 阅读(334) 评论(0) 推荐(0)
摘要: 客户需求: 需求的第二条比较难以实现,例如第一次调用返回1,第二次返回1,第三次返回2,第四次返回3。 也就是说fib函数是带状态的,每次返回的值都不同。 我们以前接触过的函数大多数都是无状态的。 简单的解决方案就是使用全局变量记录状态,而程序开发中全局变量又是不被推荐使用的,那么还有什么其它的方法 阅读全文
posted @ 2018-09-02 10:29 周伯通789 阅读(208) 评论(0) 推荐(0)