zoukankan      html  css  js  c++  java
  • C++程序设计POJ》《WEEK5 继承和派生》《复合关系和继承关系》《基类/派生类同名成员和protected访问范围说明符》《派生类的构造函数》

    继承和派生

    继承:在定义一个新的类B时,如果该类与某个已有的类A相似(指的是B拥有A的全部特点),

    那么就可以把A作为一个基类,而把B作为基类的一个派生类(也称子类).

    派生类是通过对基类进行修改和扩充得到的。在派生类中,可以扩充新的成员变量和成员函数.

    派生类一经定义后,可以独立使用,不依赖于基类.

    派生类拥有基类的全部成员函数和成员变量,不论是private、protected、public.

    在派生类的各个成员函数中,不能访问基类中的private成员。

    派生类的写法
    class 派生类名:public 基类名 { };


    派生类对象的内存空间

    派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积

    在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前

    /*001-继承和派生*/
    #include<iostream>
    #include<string> // if did not include this file
    using namespace std;
    
    class CStudent
    {
    private:
        string name;
        string id;
        char gender;
        int age;
    public:
        void PrintInfo();
        void SetInfo(const string & name_, const string & id_, int age_, char gender_);
        string GetName()
        {
            return name;
        }
    };
    class CUndergraduateStudent :public CStudent
    {
    private:
        string department;
    public:
        void QualifiedForBaoyan()
        {
            cout << "qualified for baoyan" << endl;
        }
        void PrintInfo()
        {
            CStudent::PrintInfo();//调用基类的PrintInfo
            cout << "Department:" << department << endl;
        }
        void SetInfo(const string & name_, const string & id_,
            int age_, char gender_, const string & department_)
        {
            CStudent::SetInfo(name_, id_, age_, gender_);//调用基类的SetInfo
            department = department_;
        }
    
    };// 派生类的写法是:类名: public 基类名
    
    void CStudent::PrintInfo()
    {
        cout << "name:" << name << endl;
        cout << "id:" << id << endl;
        cout << "age:" << age << endl;
        cout << "gender:" << gender << endl;
    }
    void CStudent::SetInfo(const string & name_, const string & id_, int age_, char gender_)
    {
        name = name_;
        id = id_;
        age = age_;
        gender = gender_;
    }
    
    int main()
    {
        CUndergraduateStudent s2;
        s2.SetInfo("harry potter", "1188", 19, 'm', "cs"); // "" 对应字符串 '' 对应字符
        cout << s2.GetName() << " ";
        s2.QualifiedForBaoyan();
        s2.PrintInfo();
    
        while (1);
        return 0;
    
    }

    继承关系和复合关系

    复合关系的使用

    基类/派生类同名成员 与Protected关键字

    Note: 一般来说,基类和派生类不定义同名成员变量

    访问范围说明符


    基类的private成员: 可以被下列函数访问
    •基类的成员函数
    •基类的友员函数

    基类的public成员: 可以被下列函数访问
    •基类的成员函数
    •基类的友员函数
    •派生类的成员函数
    •派生类的友员函数
    •其他的函数

    访问范围说明符: protected
    基类的protected成员: 可以被下列函数访问
    •基类的成员函数
    •基类的友员函数
    •派生类的成员函数可以访问当前对象的基类的保护成员

    #include<iostream>
    using namespace std;
    
    class base
    {
        int j;
    public:
        int i;
        void func();
    };
    
    class derived :public base
    {
    public:
        int i;
        void access();
        void func();
    };
    
    void derived::access()
    {
        j = 5; // 不能访问基类私有变量吗?
        i = 5; //引用的是派生类的 i
        base::i = 5; //引用的是基类的 i
        func();//派生类的
        base::func();//基类的
    
    
    }
    int main()
    {
        derived obj;
        obj.i = 1;
        obj.base::i;
    }
    
    
    /*基类/派生类同名成员 与Protected关键字*/
    #include<iostream>
    using namespace std;
    
    class Father
    {
    private:
        int nPrivate; //私有成员
    public:
        int nPublic; //公有成员
    protected:
        int nProtected; // 保护成员
    };
    
    class Son:public Father
    {
        void AccessFather()
        {
            nPublic = 1; // ok
            nPrivate = 1; // wrong
            nProtected = 1; // OK, 访问从基类继承的protected成员
            Son f;
            f.nProtected = 1; //wrong, f不是当前对象
        }
    };
    
    int main()
    {
        Father f;
        Son s;
        f.nPublic = 1; // Ok
        s.nPublic = 1; // Ok
        f.nProtected = 1; // error
        f.nPrivate = 1; // error
        s.nProtected = 1; // error
        s.nPrivate = 1; // error
        return 0;
    }

    派生类的构造函数

    派生类的构造函数

    派生类对象 包含 基类对象

    执行派生类构造函数之前, 先执行基类的构造函数

    派生类交代基类初始化, 具体形式:
    构造函数名(形参表): 基类名(基类构造函数实参表)
    {
    }

    派生类的构造函数

    class Bug {
    private :
    int nLegs; int nColor;
    public:
    int nType;
    Bug (int legs, int color);
    void PrintBug () { };
    };
    class FlyBug: public Bug { // FlyBug是Bug的派生类
    int nWings;
    public:
    FlyBug(int legs, int color, int wings);
    };

    FlyBug fb (2,3,4);

    在 创建 派生类的对象 时,
    •需要调用 基类的构造函数:
    初始化派生类对象中从基类继承的成员


    •在执行一个派生类的构造函数之前,
    总是先执行基类的构造函数

    调用基类构造函数的两种方式
    •显式方式:
    派生类的构造函数中  基类的构造函数提供参数
    derived::derived(arg_derived-list):base(arg_base-list)
    •隐式方式:
    派生类的构造函数中, 省略基类构造函数时
    派生类的构造函数, 自动调用基类的默认构造函数 派生类的析构函数被执行时, 执行完派生类的析构函数后, 自动调用基类的析构函数

    构造函数的调用顺序和析构函数是相反的

    创建 派生类的对象 时, 执行 派生类的构造函数 之前:
    •调用 基类 的构造函数
     初始化派生类对象中从基类继承的成员
    •调用 成员对象类 的构造函数
    初始化派生类对象中成员对象

    执行完 派生类的析构函数 后:
    •调用 成员对象类 的析构函数
    •调用 基类 的析构函数

    析构函数的调用顺序与构造函数的调用顺序相反

    /*
    派生类的构造函数
    */
    #include<iostream>
    using namespace std;
    #if 0
    class Bug
    {
    private:
        int nLegs;
        int nColor;
    public:
        int nType;
        Bug(int legs, int color);
        void PrintBug() {}
    
    };
    class FlyBug :public Bug
    {
        int nWings;
    public:
        FlyBug(int legs, int color, int wings);
    };
    Bug::Bug(int legs, int color)
    {
        nLegs = legs;
        nColor = color;
    }
    // 表达式中可以出现: FlyBug构造函数的参数
    FlyBug::FlyBug(int legs, int color, int wings) :Bug(legs, color)
    {
        nWings = wings;
    }
    int main()
    {
        FlyBug fb(2, 3, 4);
        fb.PrintBug();
        fb.nType = 1;
        //fb.nLegs = 2
        while (1);
        return 0;
    }
    #endif
    
    /*
    调用基类构造函数的两种方式
    */
    class Base
    {
    public:
        int n;
        Base(int i) :n(i)
        {
            cout << "base " << n << " constructed" << endl;
    
        }
        ~Base()
        {
            cout << "base " << n << " desstructed" << endl;
        }
    };
    
    class Derived :public Base
    {
    public:
        Derived(int i) :Base(i)
        {
            cout << "Derived constructed" << endl;
        }
        ~Derived()
        {
            cout << "derived destructed" << endl;
        }
    };
    int main()
    {
        Derived obj(3);
        while (1);
        return 0;
    }
    
    /*
    包含成员对象的派生类的构造函数
    */
    class Skill
    {
    public:
        Skill(int n)
        {
        }
    };
    
    class FlyBug :public Bug
    {
        int nWings;
        Skill sk1, sk2;
    public:
        //表达式中可以出现: FlyBug构造函数的参数, 常量
        FlyBug(int legs, int color, int wings) :Bug(legs, color), sk1(5), sk2(color)
        {
            nWings = wings;
        }
        
    };

    public继承的赋值兼容规则

    class base { };

    class derived : public base { };

    base b;

    derived d;

    1)派生类的对象可以赋值给基类对象
    b = d;
    2) 派生类对象可以初始化基类引用
    base & br = d;
    3) 派生类对象的地址可以赋值给基类指针
    base * pb = & d;

    直接基类和间接基类

    类A派生类B,类B派生类C,类C派生类D,……
    –类A是类B的直接基类
    –类B是类C的直接基类,类A是类C的间接基类
    –类C是类D的直接基类,类A、B是类D的间接基类

    在声明派生类时,只需要列出它的直接基类


    –派生类沿着类的层次自动向上继承它的间接基类


    –派生类的成员包括
    •派生类自己定义的成员
    •直接基类中的所有成员
    •所有间接基类的全部成员

    #include<iostream>
    using namespace std;
    
    class Base
    {
    public:
        int n;
        Base(int i) :n(i)
        {
            cout << "Base " << n << "constructed"<<endl;
        }
        ~Base()
        {
            cout << "Base " << n << "destructed" << endl;
        }
    };
    
    class Derived :public Base
    {
    public:
        Derived(int i) :Base(i)
        {
            cout << "derived constructed" << endl;
        }
        ~Derived()
        {
            cout << "derived destructed" << endl;
        }
    };
    class MoreDerived :public Derived
    {
    public:
        MoreDerived() :Derived(4)
        {
            cout << "more derived constructed" << endl;
        }
        ~MoreDerived()
        {
            cout << "more derived destructed" << endl;
        }
    };
    int main()
    {
        MoreDerived obj;
        while (1);
        return 0;
    }
  • 相关阅读:
    读写文件print函数操作
    协程相关
    线程池
    多线程条件
    ibm动态测试
    ubuntu 之 搜狗拼音安装
    Linux 安装 出现Could not get lock /var/lib/dpkg/lock
    Sql server
    maven 搭建
    EOS
  • 原文地址:https://www.cnblogs.com/focus-z/p/11032310.html
Copyright © 2011-2022 走看看