继承是面型对象的三大特征之一
继承用于描述类于类之间的从属关系,被继承的类称为基类或父类,继承的类称为子类
#include
using namespace std;
class Father {
public:
int getNum() {
return m_num;
}
public:
int m_num = 10;
};
class Son :public Father {
};
int main() {
Son son;
cout << son.m_num << endl;
cout << son.getNum() << endl;
return 0;
}
输出
10
10
继承之后,子类拥有了父类的属性和行为。需要注意的是,子类是否拥有父类的属性和行为,还决定于继承方式和父类的访问权限。
继承访问分为三种
语法
class 子类 :继承方式 父类
#include
using namespace std;
class Father {
private:
int m_A;
protected:
int m_B;
public:
int m_C;
};
void test() {
Father father;
// father.m_A; //不能访问private成员
// father.m_B; //不能访问protected成员
father.m_C;
}
// 公共继承
class Son1 : public Father {
public:
void func() {
// m_A; //不可访问private成员
m_B;
m_C;
}
};
void test1() {
Son1 son;
// son.m_A; //不可访问private成员
// son.m_B; //不可访问protected成员
son.m_C;
}
// 保护继承
class Son2 : protected Father {
public:
void func() {
// m_A; //不可访问private成员
m_B;
m_C;
}
};
void test2() {
Son2 son;
// son.m_A; //不可访问private成员
// son.m_B; //不可访问protected成员
// son.m_C; //不可访问public成员
}
// 私有继承
class Son3 : private Father {
public:
void func() {
// m_A; //不可访问private成员
m_B;
m_C;
}
};
void test3() {
Son2 son;
// son.m_A; //不可访问private成员
// son.m_B; //不可访问protected成员
// son.m_C; //不可访问public成员
}
C++有三种权限控制
三种继承后:
#include
using namespace std;
class Father {
public:
Father() {
cout << "father constructor" << endl;
}
~Father() {
cout << "father deconstructor" << endl;
}
};
class Son : public Father {
public:
Son() {
cout << "son constructor" << endl;
}
~Son() {
cout << "son deconstructor" << endl;
}
};
void test() {
Son son;
}
int main() {
test();
return 0;
}
构造顺序:先父类后子类
析构顺序:先子类后父类
析构和构造刚好相反
#include
using namespace std;
class Father {
public:
Father() {
m_A = 100;
}
void func() {
cout << "Father func()" << endl;
}
void func(int a) {
cout << "Father func(int a)" << endl;
}
public:
int m_A;
};
class Son : public Father {
public:
Son() {
m_A = 200;
}
void func() {
cout << "Son func()" << endl;
}
public:
int m_A;
};
void test() {
Son son;
cout << son.m_A << endl;
cout << son.Father::m_A << endl;
son.func();
son.Father::func();
son.Father::func(10);
}
int main() {
test();
return 0;
}
输出:
200
100
Son func()
Father func()
Father func(int a)
子类如果存在和父类同名的成员,则子类会覆盖父类的同名成员。用子类对象调用同名成员,访问的是子类自有的成员,如果要访问父类被覆盖的成员,需要加父类作用域。
静态成员不属于对象,属于类,所以静态成员是不被子类继承的
#include
using namespace std;
class Father {
public:
void func() {
cout << "Father func()" << endl;
}
void func(int a) {
cout << "Father func(int a)" << endl;
}
public:
static int m_A;
};
int Father::m_A = 100;
class Son : public Father {
public:
void func() {
cout << "Father func()" << endl;
}
void func(int a) {
cout << "Father func(int a)" << endl;
}
public:
static int m_A;
};
int Son::m_A = 200;
void test() {
Son son;
cout << son.m_A << endl;
cout << son.Father::m_A << endl;
cout << Father::m_A << endl;
cout << Son::m_A << endl;
}
int main() {
test();
return 0;
}
输出:
200
100
100
200
与成员变量的覆盖规则相同,使用作用域访问。
除了使用对象访问外,也可以通过类名访问。
C++允许一个类继承多个类
多继承可能存在多个父类有同名函数,需要加作用域区分
实际开发中不建议使用多继承
#include
using namespace std;
class Base1 {
public:
Base1() {
m_A = 200;
}
public:
int m_A;
};
class Base2 {
public:
Base2() {
m_A = 100;
}
public:
int m_A;
};
class Son : public Base1, public Base2 {
};
void test() {
Son son;
// cout << son.m_A << endl; //编译错误,无法定位访问哪个父类的成员
cout << son.Base1::m_A << endl;
cout << son.Base2::m_A << endl;
}
int main() {
test();
return 0;
}
200
100
同名成员需要添加作用域,否则编译出错,无法定位具体调用哪一个。
菱形继承就是一个基类,两个派生类继承基类,当前类同时继承两个派生类,形成一个菱形。
#include
using namespace std;
class Base {
public:
int m_A;
};
class SubBase1 : public Base {
};
class SubBase2 : public Base {
};
class Son : public SubBase1, public SubBase2 {
};
int main() {
Son son;
// son.m_A = 200; //产生歧义
son.SubBase1::m_A = 100;
son.SubBase2::m_A = 200;
cout << son.SubBase1::m_A << endl;
cout << son.SubBase2::m_A << endl;
return 0;
}
输出:
100
200
菱形继承主要问题是会有重复数据,导致资源浪费,可以采用虚继承解决菱形继承问题
private在子类不可访问,那是否继承了呢?
int main() {
cout << sizeof(Father) << endl;
cout << sizeof(Son1) << endl;
cout << sizeof(Son2) << endl;
cout << sizeof(Son3) << endl;
}
打印类大小
12
12
12
12
说明private也是继承了的,只是无法访问