zoukankan      html  css  js  c++  java
  • 第15章 面向对象程序设计

    面向对象的核心是:数据抽象、继承、动态绑定

    数据抽象:将类的接口与实现分离

    继承:对类型的相似关系进行定义建模

    动态绑定:忽略相似类的区别,统一使用它们的对象

    15.2基类与派生类

    class Base 
    {
    public:
        Base() = default;
        Base(int value) :value(value){}
        virtual int get_value() { return value; };
        virtual ~Base() = default;
    private:
        int value;
    protected:
        void change_value() { value++; }
    };

    基类都应该定义一个虚函数,这样在delete一个指向派生类对象的基类指针所指向new分配的空间时,能会有理想的析构函数调用(先调用派生类的析构函数,再调用基类的。否则将会仅调用基类的析构函数)。

    class Derived final:public Base
    {
    public:
        Derived() = default;
        Derived(int value) :Base(value) {}
        int get_value() override { return value*value; }
    };

    派生类覆盖基类的虚函数,可以使用(不必须,旧标准没有)override关键字,同时派生类的此函数自动成为virtual的,不管加不加virtual关键字。

    final表明这个类不能被继承。

    如果需要喜用被override的基类成员,需要加上基类的作用域Base::

    15.2.3类型转换与继承

    1. 派生类的指针或引用可以隐式转换成基类的指针引用,反之则不行。
    2. 派生类的对象和基类的对象之间不存在期望的类型转换,因为派生类赋值给基类的时候,实际发生的是执行拷贝构造函数等过程,最终得到一个新的基类对象。

    15.3虚函数/抽象基类

    我们如果想调用被override的虚函数,可以使用作用域运算符进行调用。

    如果虚函数=0,就是纯虚函数。有纯虚函数的类是抽象基类。我们不能创建抽象基类的对象。

    15.5访问控制与继承

    protect

    protect成员对类的用户来讲是不可访问的

    派生类protect继承基类,则基类的public成员降维成protect成员存在于派生类中

    派生类的成员可以通过派生类的对象访问基类的protect成员(因为2中继承过来,相当于自己的protect成员),而不能通过基类的对象访问基类的protect成员(因为1)

    private

    private成员对用类的用户来讲是不可访问的。private继承过来的基类的所有成员在派生类中都将会是私有的。

    派生类public继承的基类之间,才能够进行类型转换

    提升基类成员的访问级别

    class Base {
    public:
        std::size_t size() const { return n; }
    protected:
        std::size_t n;
    };
    class Derived : private Base {
    public:
        //本来对于使用者是private的,但是提升到了public
        using Base::size;
    protected:
        //本来对于使用者是private的,但是提升到了protected
        using Base::n;
    };

    15.6继承中类的作用域

    在对象进行成员访问的时候,首先从其静态作用域中需要成员。如果找不到,去外层基类中进行查找。

    如果派生类定义了和基类中名字相同的成员,则基类的成员在派生类的作用域中将会被隐藏。如果要使用,则可以通过基类的作用域进行调用。

    15.7构造函数与拷贝控制

    基类为虚析构函数时,使用基类的指针或引用删除(delete)派生类对象时,才能正确执行派生类的析构函数。

    基类的虚析构函数(哪怕=default)还会阻止合成的移动操作。(析构函数一般和合成的移动操作有冲突)所以派生类已没有合成的移动操作,一般应该重新定义如下:

    class Quote {
    public:
        Quote() = default;  // memberwise default initialize
        Quote(const Quote&) = default; // memberwise copy
        Quote(Quote&&) = default;  // memberwise copy
        Quote&operator=(const Quote&) = default; // copy assign
        Quote&operator=(Quote&&) = default;  // move assign
        virtual~Quote() = default;
        // other members as before
    };

    15.7.4继承的构造函数

    默认、拷贝、移动构造函数将不会被继承。

    class Base 
    {
    public:
         Base(int n) { cout << "base" << endl; }
    };
    class Derived final:public Base
    {
    public:
        using Base::Base;
        //上边这个继承的基类构造函数会被编译器产生如下代码
        //但是如果用户自定义了,基类的构造函数就会被覆盖
        //Derived(int n) :Base(n) { cout << "derived" << endl; }
    };
  • 相关阅读:
    058_从键盘读取一个论坛积分,判断论坛用户等级
    057_统计 Linux 进程相关数量信息
    bzoj3436
    bzoj1202
    bzoj1044
    bzoj2338
    bzoj1854
    bzoj1856
    830C
    bzoj2132
  • 原文地址:https://www.cnblogs.com/qiusuo/p/5131808.html
Copyright © 2011-2022 走看看