C++ Primer 学习笔记十五 —— 面向对象编程

记录笔记原则:

1.用简单易懂的语言叙述自己的理解,避免照搬原文

2.用实例说明,避免空洞

3.多做总结和横向对比,避免片面


面向对象三个基本概念

抽象;继承;动态绑定;

继承使我们简化了类的定义;

动态绑定使我们简化了接口的实现,使得所有继承层次的类可以使用同一个函数接口;


动态绑定的两个条件

通过基类的引用(或指针)调用虚函数,才发生动态绑定;


非虚函数的调用在编译阶段确定,虚函数的调用在运行阶段动态确定;


一旦函数在基类中声明为虚函数,它就一直为虚函数了,派生类中不需再次声明为virtual了;

派生类对象由两部分组成:派生类本身的成员+基类的子对象


强制调用基类的虚函数

Base *p = &derived;
p->Base::hello();



访问控制

class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
        void funcA();
};
class PublicDerived: public Base
{
    public:
        void funcB();
};
class ProtectedDerived: protected Base
{
    public:
        void funcB();
};
class PrivateDerived: private Base
{
    public:
        void funcB();
};

派生类成员不能访问基类的private成员;

对继承的成员访问由基类中的访问控制派生标号共同控制;

派生标号只是控制用户代码对基类成员的访问,派生类成员函数对基类成员的访问控制不受影响;

下面是公有派生、保护派生、私有派生下,基类成员函数、派生类成员函数、用户代码对基类成员的可访问情况:


公有派生,用户代码可访问基类的public成员;保护派生,基类中的公有成员和保护成员变成派生类中的保护成员,用户代码不能访问基类的任何成员;私有派生,基类中的公有成员和保护成员变成私有成员,用户代码不能访问基类成员;


派生类构造函数和复制控制函数

派生类构造函数初始化列表顺序:首先初始化基类,然后根据声明次序初始化派生类自身的成员;

派生类合成的析构函数不负责撤销基类对象成员,由编译器自动调用基类的析构函数;


虚析构函数

基类的析构函数必须为虚函数;

Base *p = new Derived();
delete p;
如果析构函数不是虚函数,delete将只调用基类的析构函数;


屏蔽与虚函数

同名函数,即使函数参数不同,基类成员也会被屏蔽,因为编译器一旦找到名字,就不继续找了,找到名字后再做参数检查;

struct Base
{
    int func();
};
struct Derived: public Base 
{
    int func(int);
};
Derived d;
d.func(10);    // ok,调用派生类函数
d.func();    // error,参数不匹配
d.Base::func();  // ok,强制调用基类函数
更复杂一点的例子
struct Base {
    virtual int fcn();
};
struct D1: public Base {
    int fcn(int);
};
struct D2: public D1 {
    int fcn(int);
    int fcn();
};

Base *p1 = new Base();
Base *p2 = new D1();
Base *p3 = new D2();
p1->fcn();  // ok, 调用基类函数
p2->fcn();  // ok, 调用基类函数
p3->fcn();  // ok, 调用D2类函数
上面三个调用都是动态绑定,p2的实际对象时D1,D1类没有重定义虚函数版本,所以将调用基类的虚函数版本;


编译器确定函数调用步骤

1.确定调用者的指针、引用、对象的静态类型(编译可知的直接类型);

2.在该类中查找函数,找不到在基类中继续找,如此回溯;

3.一旦找到名字,就不继续找了,并进行类型检查,这时如果发现参数不匹配就出错了;

4.如果发现该函数是虚函数,并且通过指针(引用)调用,则编译器生成代码在运行阶段动态绑定函数版本,否则,编译器直接调用该函数;


纯虚函数

意义:不想让用户创建对象,只是规范接口;

形式

virtual void hello() = 0;
含有纯虚函数的类是抽象基类;

派生类必须重定义接口;





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值