C++基础-类与对象(2)
C++-类与对象(2)-继承
继承
一个小引子
有些类之间存在特殊的关系,像下面的图一样:
定义这些类时,下级的成员除了有向上一级类的共性,还有自己的特性,这时,就可以用继承的技术,减少代码的重复
继承的基本语法
class 子类 : 继承方式 父类
- 子类:也叫派生类
- 父类:也叫基类
#include<iostream>
using namespace std;
//普通页面实现
//java页面
//class Java{
//public:
// void header(){
// cout << "首页,登录,注册(公共头部)" << endl;
// }
//
// void footer(){
// cout << "帮助中心,站内地图(公共底部)" << endl;
// }
//
// void lefter(){
// cout << "C++,Java,Phthon(公共分类列表)" << endl;
// }
//
// void conter(){
// cout << "Java学科的视频" << endl;
// }
//};
//class Python{
//public:
// ...和前面一样
// void conter(){
// cout << "Python学科的视频" << endl;
// }
//};
//class Cpp{
//public:
// ...和前面一样
// void conter(){
// cout << "C++学科的视频" << endl;
// }
//};
//继承实现页面
//公共页面类
class BagePage{
public:
void header(){
cout << "首页,登录,注册(公共头部)" << endl;
}
void footer(){
cout << "帮助中心,站内地图(公共底部)" << endl;
}
void lefter(){
cout << "C++,Java,Phthon(公共分类列表)" << endl;
}
};
//Java页面
class Java:public BagePage{
public:
void conter(){
cout << "Java学科的视频" << endl;
}
};
//Python页面
class Python:public BagePage{
public:
void conter(){
cout << "Python学科的视频" << endl;
}
};
//Cpp页面
class Cpp:public BagePage{
public:
void conter(){
cout << "C++学科的视频" << endl;
}
};
void test01(){
cout << "Java界面下载" << endl;
Java ja;
ja.header();
ja.lefter();
ja.footer();
ja.conter();
cout << "=========================" << endl;
cout << "Python界面下载" << endl;
Python py;
py.header();
py.lefter();
py.footer();
py.conter();
cout << "=========================" << endl;
cout << "C++界面下载" << endl;
Cpp cpp;
cpp.header();
cpp.lefter();
cpp.footer();
cpp.conter();
}
int main(){
test01();
return 0;
}
两次结果均是
子类中包含两大成员:1是自己增加的成员(共性) 2.是从父类中继承的过来的(共性)
继承方式
继承一共3种方式
- 公共继承
- 保护继承
- 私有继承
继承中的对象模型
从父类继承到子类的成员,那些属于子类的对象中
父类中非静态的成员属性都会被子类继承下去(私有属性只是被编译器隐藏了)
#include<iostream>
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 << "size of Son is " << sizeof(Son) << endl;
}
int main(){
test01();
return 0;
}
查看对象模型
利用开发人员命令提示工具
- 跳转盘符
- 跳转文件路径 cd 具体路径
- 查看:cl /dl reportSlingleClassLayout类名 文件名(回车)
继承中构造和析构顺序
构造:先父类后子类
析构:先子类后父类
继承中同名成员处理 方式
当我们的子类和父类出现同名的成员,如何通过子类对象来访问到子类或父类中同名的数据呢
- 访问子类同名成员:直接访问即可
- 访问父类同名成员:需要加作用域
同名的成员属性
#include<iostream>
using namespace std;
//父类:m_a = 100
//子类:m_a = 200
class Base{//父类
public:
int m_a;
Base(){
m_a = 100;
}
};
class Son:public Base{//子类
public:
int m_a;
Son(){
m_a = 200;
}
};
void test01(){
Son s;
/*=====================================================*/
cout << "子类的m_a:"<< s.m_a << endl;//直接访问
cout << "父类的m_a:" << s.Base::m_a << endl;//添加父类的作用域
/*=====================================================*/
}
int main(){
test01();
return 0;
}
同名的成员函数
如果出现同名的情况,子类中的同名函数会隐藏掉父类中所有的同名函数(包括重载函数)
#include<iostream>
using namespace std;
class Base{
public:
int m_a;
Base(){
m_a = 100;
}
void func(){
cout << "父类的m_a:" << m_a << endl;
}
};
class Son:public Base{
public:
int m_a;
Son(){
m_a = 200;
}
void func(){
cout << "子类的m_a:" << m_a << endl;
}
};
void test02(){
Son s;
/*=====================================================*/
s.func();
s.Base::func();
/*=====================================================*/
}
int main(){
test02();
return 0;
}
小总结
- 子类对象可以直接访问子类中同名的成员
- 子类加作用域可以访问父类中的成员
- 如果出现同名的情况,子类中的同名函数会隐藏掉父类中所有的同名函数
继承中同名静态处理方法
和上面是一样的哦…
- 访问子类同名成员:直接访问即可
- 访问父类同名成员:需要加作用域
我就不写喽(嘿嘿)
emmm,复习一下访问方法
//成员
Son s;
//通过对象访问
cout << "子类的m_a:"<< s.m_a << endl;//直接访问
cout << "父类的m_a:" << s.Base::m_a << endl;//添加父类的作用域
//通过类名来访问
cout << Son::m_a << endl;
cout << Son::Base::m_a << endl;
//函数
Son s;
s.func();
s.Base::func();
Son::func();
Son::Base::func();
多继承语法
C++可以一个类继承多个类(一个儿子认多个父亲…)
多继承更会触发同名的问题,要注意加作用域区分
实际开发不建议使用(经典白学)
语法
class 类名:继承方式1 父类1,继承方式2 父类2...
例子
#include<iostream>
using namespace std;
//父类1是100
//父类2是200
//子类是300
class Base1{//父类1
public:
int m_a;
Base1(){
m_a = 100;
}
};
class Base2{//父类2
public:
int m_a;
Base2(){
m_a = 200;
}
};
class Son:public Base1,public Base2{//子类
public:
int m_a;
Son(){
m_a = 300;
}
};
void test01(){
Son s;
cout << "子类的m_a:" << s.m_a << endl;
cout << "父类1的m_a:" << s.Base1::m_a << endl;
cout << "父类2的m_a:" << s.Base2::m_a << endl;
}
int main(){
test01();
return 0;
}
菱形继承
概念
-
两个派生类继承同一基类
-
又有某个类同时继承两个派生类
这样就叫做菱形继承啦,或是叫做钻石继承
但是会出现一些问题:
- 若有同名数据,要加作用域区分
- 子类相同数据可能会有多份,既浪费,又没用(用虚继承来解决,关键字:virtual)
例子
没有虚继承:
#include<iostream>
using namespace std;
class Base{//虚基类
public:
int m_age;
};
class Son1: public Base{};
class Son2: public Base{};
class GrandSon:public Son1,public Son2{};
void test01(){
GrandSon gs;
gs.Son1::m_age = 18;
gs.Son2::m_age = 28;
cout << "Son1的年龄" <<gs.Son1::m_age << endl;
cout << "Son2的年龄" <<gs.Son2::m_age << endl;
//但是GrandSon的年龄只要一个就好了,但现在有两份
//利用虚继承解决:
//继承前加关键字
cout << gs.m_age;
}
int main(){
test01();
return 0;
}
加上虚继承
class Son1:virtual public Base{};
class Son2:virtual public Base{};
void test01(){
...
cout << gs.m_age;
}