c++笔记06---继承,公有继承,继承方式对访控属性的影响,私有继承和保护继承

本文介绍了C++中的继承概念,包括公有、私有和保护三种继承方式。通过实例讲解了公有继承下基类成员在子类中的访问权限,并展示了子类构造函数的调用规则。还讨论了隐藏与重载、子类构造顺序、继承方式对访控属性的影响以及私有和保护继承的作用。最后提到了多态和虚函数的概念,强调了虚函数在实现多态中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.    继承
    class 子类名 : 继承方式1 基类1,继承方式2 基类2,. . . { }
    继承方式:
        public            公有继承(最常用方式)                “是”关系
        private        私有继承(默认缺省方式)                “拥有”关系
        protected        保护继承(看作特殊的私有继承)

    基类 派生 子类
    子类 继承 基类    
    
2.    公有继承    
    class Human {
    public:
        Human(const string& name = "", int age = 0) : m_name(name), m_age(age) {}
        // 这里要给参数设置缺省值,可以不用写缺省构造函数,如果没有,则编译器报错;
        void who() const {
            cout << m_name << m_age << endl;
        }
        void eat(const string& food) const { cout << food << endl;        // 吃饭动作,有参
    protected:                        // 可以让子类使用,如果是 private 子类就无法调用
        string m_name;
        int m_age;
    };
    class Student : public Human {
    public:
        Student(const string& name, int age, int no) : m_no(no) {        // m_no 可以在初始化列表初始化
            m_name = name;            // m_name 是继承来的,不能在初始化列表里面这样写:m_name(name);
            m_age = age;
        }
        /*
        也可以这样给 m_name 和 m_age 初始化:
            Student(const string& name, int age, int no) : Human(name, age), m_no(no) {}
        如果这样初始化,那么上面基类里的 Human 就不用设置参数缺省值;
        */
        void learn(const string& lesson) const {    // 学习动作
            cout << lesson << endl;
        }
    private:
        int m_no;                                        // 学号属性
    }
    int main() {
        Student s1("zhangfei", 25, 111);            // 在调用 Student 构造函数的时候,也在调用 Human() 的无参构造函数
        s1.who();                                        // s1 可以直接调用基类的 who 成员函数
        s1.eat("kfc");
        s1.learn();
        return 0;
    }
    
    这里 m_name 和 m_age 称作子类对象中的基类子对象;
    主函数里构造学生对象 s1 的时候,就要初始化 m_name 和 m_age,方法有三:
        a. 定义 Human 默认构造函数;
        b. 给 Human 参数表定义默认值;
        c. 在学生类构造函数初始化类表里面给 m_name 和 m_age 初始化;
    
3.    通过继承,在基类中定义的任何成员,也都成了子类的成员;
    
    但是基类的私有成员,子类虽然拥有,却不能直接访问;
    子类可以通过基类的成员函数间接访问私有成员;
    
    基类中的保护成员可以被子类直接访问;但不能在其他类和全局中被访问;
    
    任何一个子类对象中都包含着基类子对象;
    一个子类对象在任何时候都可以被视为基类对象;
    也就是说,任何时候一个子类对象的指针和引用,都可以被隐式转换为基类类型的指针或引用;
    反之不行,不过可以显式转换;
        Student s1(...);
        Human* h = &s1;                        // ok
        h -> who();                            // ok
        h -> learn();                            // error
        Student *sp;
        sp = h;                                // error,隐式转换;
        sp = static_cast<Student*> (h);        // ok,显式转换;
    这里 h 虽然指向 s1,但是不能访问 Student 的成员函数;
    h 的访问范围由它的类型 Human 决定;
    Human 访问范围小于 Student,Student 转为 Human 是往小里转,安全,所以计算机可以隐式转换;
    而反过来则不安全,必须显式转换;
   &n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值