继承
- 一、继承基本语法
- 二、继承方式
- 1、公共继承public
- 2、保护继承protected
- 3、私有继承private
- 三、对象模型
- 四、继承中的构造与析构顺序
- 五、同名成员处理方式
- 同名静态成员处理方法
- 六、多继承语法(不建议使用)
- 七、菱形继承(钻石继承)
一、继承基本语法
减少重复代码
语法:class 子类:继承方式 父类
子类也成为派生类,父类成为基类
class Student {
public:
void Cource() {
cout << "学生课程" << endl;
}
void Source() {
cout << "学生成绩" << endl;
}
void Info() {
cout << "学生信息" << endl;
}
};
class Banji :public Student {
public:
void Peoplenum() {
cout << "14班级人数" << endl;
}
};
class Nianji :public Student {
public:
void Num() {
cout << "年纪人数" << endl;
}
};
二、继承方式
父类:
class S {
public:
int a;
protected:
int b;
private:
int c;
};
1、公共继承public
class A :public S {
public:
void fun() {
a = 10;
b = 20;
c = 30;//不可访问,私有变量
cout << a << "\t" << b << "\t"<< endl;
}
};
void test() {
A a1;
a1.a = 100;
a1.b = 200;//不可访问,保护变量
a1.c = 300;//不可访问,私有变量
a1.fun();
}
2、保护继承protected
class B :protected S {
public:
void fun() {
a = 10;//公有变保护
b = 20;
//c = 30;//不可访问
cout << a << "\t" << b << "\t" << endl;
}
};
void test() {
B a1;
a1.a = 100;//不可访问,变为了保护变量
a1.b = 200;//不可访问
a1.c = 300;//不可访问
a1.fun();
}
3、私有继承private
class C :private S {
public:
void fun() {
a = 10;//公有变保护
b = 20;
//c = 30;//不可访问
cout << a << "\t" << b << "\t" << endl;
}
};
//孙类
class Grand :public C {
public:
void fun() {
a = 10;//已变为私有,不可访问
b = 20;//不可访问
//c = 30;//不可访问
cout << a << "\t" << b << "\t" << endl;
}
};
void test() {
B a1;
a1.a = 100;//不可访问,变为了私有变量
a1.b = 200;//不可访问,变为了私有变量
a1.c = 300;//不可访问
a1.fun();
}
三、对象模型
父类中所有的非静态成员属性都会被子类继承,父类中私有的成员属性被编译器隐藏不可访问但被继承。
class S {
public:
int a;
protected:
int b;
private:
int c;
};
class A :public S {
public:
int d;
};
void test() {
cout << "size of A子类:" << sizeof(A) << endl;//父类中所有的非静态成员属性都会被子类继承,父类中私有的成员属性被编译器隐藏不可访问但被继承。
}
注:利用开发人员命令工具查看对象模型
首先打开开始文档的vs开发人员命令提示工具
查看命名:cl /d1 reportSingleClassLayout查看的类名 所属文件名
四、继承中的构造与析构顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数
先构造父类,再构造子类,析构的顺序与构造的顺序相反
五、同名成员处理方式
1、访问子类同名成员,直接访问即可
2、访问父类同名成员,需要加载作用域(子类实例化名.父类名::成员属性/函数
)
3、当子类中出现和父类同名的成员函数,子类的同名成员函数会隐藏掉父类中所有同名成员函数(包括重载的),如果想访问到需要加作用域
同名静态成员处理方法
规则和同名成员处理方式一样,只多了一种访问方式。
class S {
public:
static int a;
static void fun() {
cout << "子类下的函数" << endl;
}
static void fun(int a) {
cout << "子类下的函数(有参数)" << endl;
}
protected:
int b;
private:
int c;
};
int S::a = 10;
class A :public S {
public:
int d;
static int a;
static void fun() {
cout << "子类下的函数" << endl;
}
};
int A::a = 100;
void test() {
//通过对象访问
A a1;
cout <<"子类下" << a1.a << endl;
cout << "父类下" << a1.S::a << endl;
a1.fun();
a1.S::fun();
//通过类名
cout << "子类下" << A::a << endl;
//第一个::代表通过类名方式访问,第二个::代表访问父类作用域下
cout << "父类下" << A::S::a << endl;
A::fun();
A::S::fun();
A::S::fun(100);
}
六、多继承语法(不建议使用)
语法:class 子类:继承方式 父类1,继承方式 父类2...
可能会引发父类中同名,不明确出现二义性,可以使用作用于访问父类中的同名。
可以使用对象模型查看
class S {
public:
int a;
S() {
a = 10;
}
};
class S1 {
public:
int b;
S1() {
b = 20;
}
};
class A :public S ,public S1{
public:
int c;
int d;
A() {
c = 30;
d = 40;
}
};
七、菱形继承(钻石继承)
概念:
1、两个派生类继承同一个基类
2、又有某个类同时继承两个派生类
资源浪费
利用虚继承解决菱形继承的问题,加关键字virtual
,父类被称为虚基类。虚继承数据只有一个。