原创 【博客大赛】《C++ Primer》学习笔记(33)面向对象的编程

2016-4-29 20:11 1190 11 12 分类: MCU/ 嵌入式 文集: Qt和Cpp

很多应用里面,会有相互联系而又细微不同的概念。
OOP(Object-oriented Programming)非常适合用在这样的场合。

15.1 Basic Concepts
----------------------------------------------------------------
OOP的核心思想是:
data abstraction
inheritance
dynamic binding

派生类必须在自己的类里,定义基类的所有virtual函数。
使用基类做参数的场合,我们也可以使用派生类,这里用到了dynamic binding的技术。
dynamic binding是直到运行的时候,才知道调用哪个类的virtual函数,因此它又称为:
run-time binding

15.2 Defining Base and Derived Classes
----------------------------------------------------------------
基类必须定义一个virtual的析构函数。
virtual关键字不可用在构造函数上,不可出现在函数的定义上(只能用在类中的函数声明)。
派生类继承的virtual函数,会被隐式的设置为virtual。

protected表示,这个成员可以被派生类访问,但不能被外部访问。

derived-to-base conversion:
我们可以将一个基类的引用或指针,绑定到派生类(的基类part)上,比如:
Bulk_quote bulk;
Quote *p = &bulk;
Quote &r = bulk;

派生类不能执行基类的成员初始化,因为:
Each class controls how its members are initialized.

如果派生类想实现基类的成员初始化,它需要在自己的构造函数中调用基类的构造函数。
比如下面的代码:
Bulk_quote(string isbn, double price) : Quote(isbn, price) {}

如果基类中有一个static成员,那么所有的派生类和基类都只会包含一个它。

声明派生类的时候,不能够加上后面的派生列表:
class Bulk_quote : public Quote;  //error
class Bulk_quote;                 //OK

final关键字,用来告诉编译器这个类不能被继承。

15.3 Virtual Functions
----------------------------------------------------------------
当一个virtual函数被调用时,直到运行时编译器才知道应该调用哪一个版本。
这是通过引用或指针的dynamic type来判断的。

非virtual的函数在编译时就能指定。
当使用override关键字时,编译器会为我们检查此函数是不是override了基类中的函数。
virtual函数应该使用同样的基类default values参数,不管时基类还是派生类。

15.4 Abstract Base Classes
----------------------------------------------------------------
如果定义一个纯虚函数?
在函数的末尾添加“= 0”:
class Pure_quote : public Quote {
public:
    Pure_quote() = default;
    virtual double net_price(size_t n) const = 0;
};

这也意味着我们不能够定义Pure_quote的对象,而是只能继承它。
具备纯虚函数的类,称为抽象基类。

15.5 Access Control and Interitance
----------------------------------------------------------------
protected成员可以被friend或者派生类访问。
friend或者派生类只能通过派生的对象来访问,不能通过基类来访问,比如:
class Sneaky : public Base  {
    friend void clobber(Sneaky&);  // can access Sneaky::prot_mem
    friend void clobber(Base&);    // can't access Base::prot_mem
    int j;                          // j is private by default
};

如果派生的friend可以访问Base,那么只需要随意定义一个这样的派生类即可。

如果D类继承自B类:
 * 只有当D类以public的方式继承B的时候,用户代码才可以使用derived-to-base转换。
 * D的成员函数以及D的友元,能够使用这种转换,无论如何继承都可以。
 * D派生类的成员函数以及它的友元,只有在public或者protected继承时,才能使用这种转换。

友元不可继承。
using可以用来改变访问的level。

15.6 Class Scope under Inheritance
----------------------------------------------------------------
派生类的scope nested in基类中。
派生类的name会覆盖它的基类中的name(不推荐使用派生类的name覆盖掉基类的name)。
scope操作符可以用来指定name的lookup。

派生类的函数会覆盖它的基类中的同名函数,即使它们的参数列表不一样,因为它们的scope不同。

15.7 Constructors and Copy Control
----------------------------------------------------------------
基类必须定义一个虚的析构函数。
当删除一个Quote指针时,可能实际删除的却是一个Bulk_quote指针,此时就要调用后者的析构函数。

当派生类进行copy操作时,它的基类会调用构造函数,除非我们显式的指定使用copy/move。
assig操作也是一样的。
如果基类没有定义assign操作或者copy/move,编译器会自动调用合适的copy或其他函数。

在构造函数或析构函数里面调用的virtual函数,一定是构造函数/析构函数本身的类所拥有的那个。
using关键字,可以用来使得派生类继承基类的构造函数,
比如:
class Bulk_quote : public Disc_quote {
public:
    using Disc_quote::Disc_quote; // inherit Disc_quote's constructors
    double net_price(std::size_t) const;
};

15.8 Containers and Inheritance
----------------------------------------------------------------
一般来说,和继承相关的类,不要存放在容器中,
因此我们很难确认,是存基类还是存派生类;使用指针(smart指针)可以解决这个问题。

 

文章评论1条评论)

登录后参与讨论

用户593939 2016-4-29 22:58

写的好,参考和学习
相关推荐阅读
DiracFatCat 2018-09-05 12:14
【博客大赛】卡尔曼滤波学习笔记(11)从位置估计速度
卡尔曼滤波器,不仅仅是一个低通滤波器,否则也不会持续发展50年。 示例:桑先生需要测试高速列车的性能。测试的目的是判断列车在直线上能否保持80m/s的速度。速度和位置每0.1秒测量一次,但是由于...
DiracFatCat 2018-08-31 19:32
【博客大赛】卡尔曼滤波学习笔记(10)一个简单的示例
《Kalman Filtering: Theory and Practice Using MATLAB》第三章,看不懂,暂时略过。《Kalman Filtering: Theory and Pract...
DiracFatCat 2018-07-19 15:09
对sed命令的练习
sed是流编辑器。它每次处理一个输入,因此很有效率。官方手册:https://www.gnu.org/software/sed/manual/sed.html学习Linux命令,当然要阅读官方手册,所...
DiracFatCat 2018-06-19 15:10
【博客大赛】卡尔曼滤波学习笔记(八)可观测性和可控制性 ...
可观测性是指,在给定模型的情况下,动力学系统的状态是否由它的输入输出唯一确定。可观测性是系统模型的特征。如果传感器矩阵H是可逆的,则本系统可观测,因为有:如果传感器矩阵H某些时候是不可逆的,则本系统仍...
DiracFatCat 2018-06-19 10:56
【博客大赛】卡尔曼滤波学习笔记(七)Z变换
如果我们仅仅对离散线性系统感兴趣,那么就使用下面这个表达式:如果u是常量,那么可以写成:为了简化表达式,我们可以将上面写成:离散线性时不变系统的Φ求解,可以使用Z变换。(* 由于本人已经忘记了Z变换的...
DiracFatCat 2018-06-19 10:54
【博客大赛】卡尔曼滤波学习笔记(六)拉普拉斯变换
对于线性时变/时不变系统,求解Φ(t)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
我要评论
1
11
关闭 站长推荐上一条 /2 下一条