C++学习 --- 类和对象之继承

六、继承

1、继承的基本语法

菜鸟写法:

#include <iostream>
#include <string>
using namespace std;
//普通实现页面
//Java页面
class Java {
public:
    void header() {
        cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
    }
    void footer() {
        cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
    }
    void left() {
        cout << "Java、Python、C++、...(公共分类列表)" << endl;
    }
    void content() {
        cout << "Java 学科视频" << endl;
    }
};
​
//Python页面
class Python {
public:
    void header() {
        cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
    }
    void footer() {
        cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
    }
    void left() {
        cout << "Java、Python、C++、...(公共分类列表)" << endl;
    }
    void content() {
        cout << "Python 学科视频" << endl;
    }
};
​
//C++页面
class CPP {
public:
    void header() {
        cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
    }
    void footer() {
        cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
    }
    void left() {
        cout << "Java、Python、C++、...(公共分类列表)" << endl;
    }
    void content() {
        cout << "C++ 学科视频" << endl;
    }
};
​
void test01() {
    cout << "Java 下载视频页面如下: " << endl;
    Java ja;
    ja.header();
    ja.footer();
    ja.left();
    ja.content();
​
    cout << "-----------------------" << endl;
    cout << "Python 下载视频页面如下: " << endl;
    Python py;
    py.header();
    py.footer();
    py.left();
    py.content();
​
    cout << "-----------------------" << endl;
    cout << "C++ 下载视频页面如下: " << endl;
    CPP cpp;
    cpp.header();
    cpp.footer();
    cpp.left();
    cpp.content();
​
}
​
int main() {
    test01();
    system("pause");
    return 0;
}

 

继承写法:

#include <iostream>
#include <string>
using namespace std;
​
/*  
    继承实现页面:
    好处:减少重复代码
    语法: class 子类:继承方式 父类
    子类也称为 派生类
    父类也称为 基类
*/class BasePage {
public:
    void header() {
        cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
    }
    void footer() {
        cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
    }
    void left() {
        cout << "Java 、Python、C++、...(公共分类列表)" << endl;
    }
};
​
//Java页面
class Java :public BasePage {
public:
    void content() {
        cout << "Java 学科视频" << endl;
    }
};
​
//Python页面
class Python :public BasePage {
public:
    void content() {
        cout << "Python 学科视频" << endl;
    }
};
​
//C++页面
class CPP :public BasePage {
public:
    void content() {
        cout << "C++ 学科视频" << endl;
    }
};
​
void test01() {
    cout << "Java 下载视频页面如下: " << endl;
    Java ja;
    ja.header();
    ja.footer();
    ja.left();
    ja.content();
​
    cout << "-----------------------" << endl;
    cout << "Python 下载视频页面如下: " << endl;
    Python py;
    py.header();
    py.footer();
    py.left();
    py.content();
​
    cout << "-----------------------" << endl;
    cout << "C++ 下载视频页面如下: " << endl;
    CPP cpp;
    cpp.header();
    cpp.footer();
    cpp.left();
    cpp.content();
}
​
int main() {
    test01();
    system("pause");
    return 0;
}

2、继承方式

 

#include <iostream>
#include <string>
using namespace std;
​
//继承方式
//公共继承
class Base1 {
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;
​
};
​
//public继承
class Son1 :public Base1 {
public:
    void func() {
        m_A = 10;   //父类中的public成员 ,子类中 public
        m_B = 10;   //父类中的protected成员 ,子类中 protected
        //m_C = 10;//父类中的private成员 ,子类中访问不到
​
    }
};
​
//protected继承
class Son2:protected Base1 {
public:
    void func() {
        m_A = 100;  //父类中的public成员, 子类中 protected
        m_B = 100;  //父类中的protected成员 ,子类中 protected
        //m_C = 10;//父类中的private成员 ,子类中访问不到
    }
};
​
//private继承
class Son3 :private Base1 {
public:
    void func() {
        m_A = 100;  //父类中的public成员, 子类中 private
        m_B = 100;  //父类中的protected成员 ,子类中 private
        //m_C = 10;//父类中的private成员 ,子类中访问不到
    }
};
​
class GrandSon3 :public Son3{
public:
    void func() {
        //m_A = 100; //子类访问不到父类Son3的私有
        //m_B = 100; //子类访问不到父类Son3的私有
        //m_B = 100; //子类访问不到父类Son3的私有
    }
};
​
void test01() {
    Son1 s1;
    s1.m_A = 100;
    //s1.m_B = 100; //类外访问不到protected 成员
​
    Son2 s2;
    //s2.m_A = 100; //m_A 变为了protected,类外访问不到 
​
    Son3 s3;
    //s3.m_A = 100;   //m_A 变为了private,类外访问不到
    //s3.m_B = 100;   //m_B 变为了private,类外访问不到
}
​
int main() {
    test01();
    system("pause");
    return 0;
}

 

3、继承中的对象模型

#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() {
    //16
    //父类中所有非静态的成员属性都会被子类继承下去
    //父类中私有成员属性 是被编译器给隐藏了,因此访问不到,但是确实是被继承下去了
    cout << "size of son = " << sizeof(Son) << endl;
}
​
int main() {
    test01();
    system("pause");
    return 0;
}

利用开发人员命令提示工具查看对象模型


 

跳转盘符 E

跳转到文件路径 cd 具体路径下

查看命令

cl /d1 reportSingleClassLayout类名 文件名

4、继承中构造和析构顺序

#include <iostream>
#include <string>
using namespace std;
​
//继承中的构造和析构顺序
class Base {
public:
    Base() {
        cout << "Base 构造函数!" << endl;
    }
    ~Base() {
        cout << "Base 析构函数!" << endl;
    }
};
​
class Son :public Base {
public:
public:
    Son() {
        cout << "Son 构造函数!" << endl;
    }
    ~Son() {
        cout << "Son 析构函数!" << endl;
    }
};
​
void test01() { 
    //继承中的构造和析构顺序如下:
    //先构造父类,再构造子类,析构的顺序与构造的顺序相反
    
    Son s;
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}

 

5、继承同名成员处理方式

#include <iostream>
#include <string>
using namespace std;
​
//继承中同名成员处理
class Base {
public:
    Base() {
        m_A = 100;
    }
    void func() {
        cout << "Base 下的 func() 函数调用 " << endl;
    }
​
    void func(int a) {
        cout << "Base 下的 func(int a) 函数调用 " << endl;
    }
    int m_A;
};
​
class Son :public Base {
public:
    Son() {
        m_A = 200;
    }
    void func() {
        cout << "Son 下的 func() 函数调用 " << endl;
    }
    
    int m_A;
};
​
//同名成员属性的处理方式
void test01() { 
    Son s;
    cout << "Son 下的 m_A = " << s.m_A << endl;
    //如果通过子类对象访问到父类同名成员,需要加作用域
    cout << "Base 下的 m_A = " << s.Base::m_A << endl;
}
​
//同名成员函数的处理方式
void test02() {
    Son s;
    //同名时,直接调用是子类中的同名成员
    s.func();
    //如何调用到父类中的同名成员函数?
    s.Base::func();
    //如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏
    //掉父类中所有同名成员(重载)函数
    //如果相访问到父类中被隐藏的同名成员函数,需要加作用域
    s.Base::func(100);
}
​
int main() {
    test01();
    test02();
​
    system("pause");
    return 0;
}

 

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

static关键字加上后变成静态成员

静态成员变量:所有对象共享同一份数据,定义阶段分配内存,类内声明,类外初始化

静态成员函数:只能访问静态成员变量,不能访问非静态成员变量,只有一份,所有的对象共享同一份函数实例

#include <iostream>
#include <string>
using namespace std;
​
//继承中的同名静态成员处理方式
class Base {
public:
    static int m_A;
    static void func() {
        cout << "Base -- static void func()" << endl;
    }
​
    static void func(int a) {
        cout << "Base -- static void func(int a)" << endl;
    }
};
int Base::m_A = 100;
​
class Son :public Base {
public:
    static int m_A;
    static void func() {
        cout << "Son -- static void func()" << endl;
    }
};
int Son::m_A = 200;
​
//同名静态成员属性
void test01() {
    //1.通过对象访问数据
    cout << "通过对象访问 :" << endl;
    Son s;
    cout << "Son 下 m_A = " << s.m_A << endl;
    cout << "Base 下 m_A = " << s.Base::m_A << endl;
    
    //2.通过类名访问数据
    cout << "通过类名访问 :" << endl;
    cout << "Son 下 m_A = " << Son::m_A << endl;
​
    //两个::的含义
    //第一个::代表通过类名方式访问
    //第二个::代表访问父类作用域下
    cout << "Base 下 m_A = " << Son::Base::m_A << endl;
​
}
//同名静态成员函数
void test02() {
    //1.通过对象访问数据
    cout << "通过对象访问 :" << endl;
    Son s;
    s.func();
    s.Base::func();
​
    //2.通过类名访问数据
    cout << "通过类名访问 :" << endl;
    Son::func();
    //子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数
    //如果想访问父类中被隐藏同名成员,需要加作用域
    Son::Base::func();  
    Son::Base::func(100);
}
​
int main() {
    test01();
    test02();
​
    system("pause");
    return 0;
}

 

7、多继承语法

#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;
};
​
//子类 需要继承Base1和Base2
//语法:class 子类:继承方式 父类1,继承方式 父类2
class Son :public Base1, public Base2 {
public:
    Son() {
        m_C = 300;
        m_D = 400;
    }
    int m_C;
    int m_D;
};
​
​
void test01() {
    Son s;
    cout << "sizeof(Son) = " << sizeof(s) << endl;
    //当父类中出现同名成员,需要加作用域区分
    //实际开发中不建议做多继承
    cout << "Base1::m_A = " << s.Base1::m_A << endl;
    cout << "Base2::m_A = " << s.Base2::m_A << endl;
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}

 

8、菱形继承

#include <iostream>
#include <string>
using namespace std;
​
//菱形继承
//动物类
class Animal {
public:
    int m_Age;
};
​
//羊类
//在继承前加上关键字virtual
class Sheep :virtual public Animal {};
​
//驼类
//在继承前加上关键字virtual 变为虚继承
//Animal类称为 虚基类
class Camels :virtual public Animal {};
​
//羊驼类
class Alpacas :public Sheep, public Camels {};
​
void test01() {
    Alpacas as;
    //当出现菱形继承时,两个父类拥有相同数据,需要加以作用域区分
    
    as.Sheep::m_Age = 18;
    as.Camels::m_Age = 28;
​
    cout << "as.Sheep::m_Age = " << as.Sheep::m_Age << endl;
    cout << "as.Camels::m_Age = " << as.Camels::m_Age << endl;
    
    //对于羊驼类这份数据只要有一份就可以了,菱形继承导致数据有两份,资源浪费
    //利用虚继承,解决以上问题
    //当使用虚继承后,只有一份数据
    cout << "as.m_Age = " << as.m_Age << endl;
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}

 

虚继承解决菱形继承的问题

 

posted @ 2021-08-18 11:39  yiwenzhang  阅读(54)  评论(0编辑  收藏  举报