C++ 类和对象学习笔记(四)继承

6. 继承

6.1继承的基本语法

csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 公共的页面
// 继承的好处:减少重复代码
// 语法:class 子类 : 继承方式 父类
class BasePage{
public:
    void header(){
        cout << "首页 、公开课" << endl;
    }
    void footer(){
        cout << "版权所有" << endl;
    }
    void left(){
        cout << "左侧广告" << endl;
    }
};

class Java : public BasePage{
public:
    
    void content(){
        cout << "java 文章内容" << endl;
    }
};

class Python : public BasePage{
public:
    void content(){
        cout << "python 文章内容" << endl;
    }
};
void test01(){
    cout << "java 课程页面" << endl;
    Java j;
    j.header();
    j.footer();
    j.left();
    j.content();

    cout << "python 课程页面" << endl;
    Python p;
    p.header();
    p.footer();
    p.left();
    p.content();

}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}

6.2 继承方式

继承的语法:class 子类 : 继承方式 父类

继承的三种方式

  1. 公共继承
  2. 保护继承
  3. 私有继承
csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 公共的页面
// 继承的好处:减少重复代码
// 语法:class 子类 : 继承方式 父类

class Base1{
public:
    int m_A;
    int m_B;
private:
    int m_C;
};

class Son1 : public Base1{
public:
    Son1(){
        m_A = 100;
        m_B = 200;
    }
    void func(){
        cout << "son1 m_A = " << m_A  << " m_B = " << m_B << endl;
    }
};

class Son2 : protected Base1{
public:
    Son2(){
        m_A = 100; // 父类的公共权限,在子类中变为保护权限
        m_B = 200;
    }
    void func(){
        cout << "son2 m_A = " << m_A  << " m_B = " << m_B << endl;
    }
};

class Son3 : private Base1{
public:
    Son3(){
        m_A = 100; // 父类的公共权限,在子类中变为私有权限
        m_B = 200;
    }
    void func(){
        cout << "son3  m_A = " << m_A  << " m_B = " << m_B << endl;
    }
};

class GrandSon : public Son3{
public:
    void func(){
        // m_A = 100; // 到了Son3 类中,m_A 变为私有权限,不可以访问
    }
};

void test01(){
    Son1 s1;
    s1.m_A = 100;
    s1.func();

    Son2 s2;
    // s2.m_A = 100; // 保护权限下,不可以访问 
    s2.func();

    Son3 s3;
    // s3.m_A = 100; // 私有权限下,不可以访问
    s3.func();
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;

6.3 继承中的对象模型

csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 继承中的对象模型

class Base {
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;    
};

class Son : public Base {
public:
    int m_D;
};

void test01() {
    // 父类中所有非静态成员属性,都会被子类继承下来
    // 父类中私有成员属性是被编译器给隐藏了,因此是访问不到的,但是确实是继承下来的
    cout << "sizeof Son = " << sizeof(Son) << endl;
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}

6.4 继承中的构造和析构顺序

csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 继承中的对象模型

class Base {
public:
    Base() {
        cout << "Base Constructor" << endl;
    }
    int m_A;
protected:
    int m_B;
private:
    int m_C;   

public:
    ~Base() {
        cout << "Base Destructor" << endl;
    }
};

class Son : public Base {
public:
    Son() {
        cout << "Son Constructor" << endl;
    }
    int m_D;
    ~Son() {
        cout << "Son Destructor" << endl;
    }
};

void test01() {
    // 继承中的构造和析构顺序
    // 先构造父类,再构造子类,析构顺序与构造相反
    Son son;
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}

6.5 继承同名成员处理方式

访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 继承同名成员处理方式
class Base{
public:
    Base(){
        m_A = 100;
    }
    int m_A;
    void func(){
        cout << "Base func" << endl;
    }

    void func(int a){
        cout << "Base func a: " << a << endl;
    }
};

class Son:public Base{
public:
    Son(){
        m_A = 200;
    }
    int m_A;
    void func(){
        cout << "Son func" << endl;
    }
};

// 同名成员处理方式
void test01(){
    Son son;
    cout << son.m_A << endl;
    // 如果通过子类对象访问父类同名成员,需要加作用域限定符
    cout << son.Base::m_A << endl; 
}

// 同名成员函数处理方式
void test02(){
    Son son;
    son.func();
    // 如果通过子类对象访问父类同名成员函数,需要加作用域限定符
    son.Base::func();
    // 如果子类中出现和父类同名成员函数,子类的同名成员函数会隐藏掉父类所有同名成员函数
    // 如果想访问父类中被隐藏的同名成员函数,需要加作用域限定符
    son.Base::func(1000);
}

int main(int argc, char const *argv[]) {
    test02();
    return 0;
}

6.6 继承同名静态成员处理方式

静态成员和非静态成员,处理方式一致
访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 继承同名静态成员处理方式
class Base{
public:
    static int m_A;
    static void func(){
        cout << "Base func" << endl;
    }

    static void func(int a){
        cout << "Base func a: " << a << endl;
    }
};

int Base::m_A = 100;

class Son:public Base{
public:
    static int m_A;
    static void func(){
        cout << "Son func" << endl;
    }
};
int Son::m_A = 200;

// 同名成员处理方式
void test01(){
    Son son;
    cout << son.m_A << endl;
    // 如果通过子类对象访问父类同名成员,需要加作用域限定符
    cout << son.Base::m_A << endl; 

    cout << Son::m_A << endl;
    // 第一个:: 代表通过类名方式访问,第二个:: 代表访问父类作用域下
    cout << Son::Base::m_A << endl;
}

// 同名成员函数处理方式
void test02(){
    Son son;
    son.func();
    Son::func();
    // 如果通过子类对象访问父类同名成员函数,需要加作用域限定符
    son.Base::func();
    Son::Base::func();
    // 如果子类中出现和父类同名成员函数,子类的同名成员函数会隐藏掉父类所有同名成员函数
    // 如果想访问父类中被隐藏的同名成员函数,需要加作用域限定符
    son.Base::func(1000);
}

int main(int argc, char const *argv[]) {
    test02();
    return 0;
}

6.7 多继承语法

csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 多继承语法
class Base1 {
public:
    Base1() {
        m_A = 100;
    }
    int m_A;
};

class Base2 {

public:
    Base2() {
        m_A = 200;
    }
    int m_A;

};

// 多继承语法
// 语法: class 子类 : 继承方式 父类1, 继承方式 父类2...

class Son : public Base1, public Base2 {
public:
    Son() {
        m_C = 300;
    }

    int m_C;
    int m_D;
};

void test01() {
    Son s;
    cout << sizeof(s) << endl;
    // 当父类出现同名成员变量时,需要加作用域区分
    cout << "m_A = " << s.Base1::m_A << endl;
    cout << "m_B = " << s.Base2::m_A << endl;
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}

6.7 菱形继承

csharp 复制代码
#include <iostream>
#include <string>

using namespace std;

// 菱形继承
// 两个派生类继承同一个基类,又有某个类同时继承两个派生类,这种继承称为菱形继承或钻石继承。

class Animal {
public:
    int age;
};

// 利用虚继承,解决菱形继承时,数据冗余问题
// 继承之前加上virtual关键字,称为虚继承
// Animal 类称为虚基类
// 羊
class Sheep :virtual public Animal {
};

// 驼类

class Camel :virtual public Animal {

};

// 羊驼
class SheepCamel : public Sheep, public Camel {
};

void test01() {
    SheepCamel sc;
    sc.Sheep::age = 10;
    sc.Camel::age = 20;
    // 当菱形继承时,两个派生类共享数据,如果修改数据,会造成二义性,需要加作用域
    cout << "sc.Sheep::age = " << sc.Sheep::age << endl;
    cout << "sc.Camel::age = " << sc.Camel::age << endl;
    cout << "sc.age = " << sc.age << endl;

    cout << "sizeof(sc) = " << sizeof(sc) << endl;
    // 菱形继承时,会产生两个实例,浪费资源

    Sheep s;
    s.age = 10;
    cout << "s.age = " << s.age << endl;
    cout << "sizeof(s) = " << sizeof(s) << endl;

}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}
相关推荐
tekin5 分钟前
Go、Java、Python、C/C++、PHP、Rust 语言全方位对比分析
java·c++·golang·编程语言对比·python 语言·php 语言·编程适用场景
小禾苗_1 小时前
C++ ——继承
开发语言·c++
OrangeJiuce2 小时前
【QT中的一些高级数据结构,持续更新中...】
数据结构·c++·qt
东方芷兰3 小时前
伯克利 CS61A 课堂笔记 11 —— Mutability
笔记·python
程序员-King.5 小时前
【接口封装】——13、登录窗口的标题栏内容设置
c++·qt
萌の鱼5 小时前
leetcode 2826. 将三个组排序
数据结构·c++·算法·leetcode
RAN_PAND6 小时前
STL介绍1:vector、pair、string、queue、map
开发语言·c++·算法
mit6.8248 小时前
[实现Rpc] 通信-Muduo库的实现 | && 完美转发 | reserve | unique_lock
c++·网络协议·rpc
快下雨了L9 小时前
C++面试笔记(持续更新...)
笔记