C++类继承学习笔记
继承权限控制:
继承权限分为public, protected, private,会修改基类的属性、成员在派生类的访问权限控制,对于基类的public、protected属性、成员,可以使用using声明来修改其访问权限控制
#include <iostream>
using namespace std;
class Base{
public:int property_public{};
protected:int property_protected{};
private:int property_private{};
};class Derived_public:public Base {
public:void func_test(){cout << property_public << endl;cout << property_protected << endl;//cout << property_private << endl;//报错,不可访问}
};class Derived_protected:protected Base{
public:void func_test(){cout << property_public << endl;cout << property_protected << endl;//cout << property_private << endl;//报错,不可访问}
};class Derived_private: private Base{
public:void func_test(){cout << property_public << endl;cout << property_protected << endl;//cout << property_private << endl;//报错,不可访问}
};
class Derived_protected_using:protected Base{
public:using Base::property_protected; //转为public属性
private:using Base::property_public;//转为private属性
};
int main(){Derived_public derived_public;cout << derived_public.property_public << endl;//cout << derived_public.property_protected << endl;// 报错 protected成员对外界不可访问Derived_protected derived_protected;//cout << derived_protected.property_public << endl;//报错 protected成员对外界不可访问Derived_protected_using derived_protected_using;cout << derived_protected_using.property_protected << endl;//可以,已经通过using转为publiccout << derived_protected_using.property_public << endl;//报错,已通过using转为private
}
继承的构造函数与析构函数调用:
普通继承:
先调用最基类的构造函数,再调用类属性的构造函数,最后调用自身构造函数
析构函数与构造函数的调用顺序相反
#include <iostream>
using namespace std;
class Base1{
public:Base1(){cout << "Base1 is constructed" << endl;}~Base1(){cout << "Base1 is destroyed" << endl;}
};class Base2:public Base1{
public:Base2(){cout << "Base2 is constructed" << endl;}~Base2(){cout << "Base2 is destroyed" <<endl;}
};class Property{
public:Property(){cout << "Property is constructed" << endl;}~Property(){cout << "Property is destroyed" << endl;}
};class Derived:public Base2{
public:Property p{};Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};int main(){Derived d{};return 0;
}
输出:
Base1 is constructed
Base2 is constructed
Property is constructed
Derived is constructed
Derived is destroyed
Property is destroyed
Base2 is destroyed
Base1 is destroyed
继承多个基类:
按顺序调用基类的构造函数,最后调用自身的构造函数
析构顺序与构造相反
//修改Derived继承方式
//同时取消Base2对Base1的继承
class Derived:public Base2,public Base1{
public:Property p{};Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};
输出:
Base2 is constructed
Base1 is constructed
Property is constructed
Derived is constructed
Derived is destroyed
Property is destroyed
Base1 is destroyed
Base2 is destroyed
虚继承与普通继承混合:
优先调用虚继承的基类构造函数,再按顺序调用普通继承的
析构顺序与构造相反
//再修改Derived继承方式
class Derived:public Base1,virtual public Base2{
public:Property p{};Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};
输出:
Base2 is constructed
Base1 is constructed
Property is constructed
Derived is constructed
Derived is destroyed
Property is destroyed
Base1 is destroyed
Base2 is destroyed
全是普通继承,但是基类中有虚基类(该类虚继承过别的基类):
优先调用虚继承的基类,之后再按顺序调用普通继承的调用函数
析构与构造顺序相反
//添加Base3和Base4
class Base3:virtual public Base1{
public:Base3(){cout << "Base3 is constructed" << endl;}~Base3(){cout << "Base3 is destroyed" << endl;}
};
class Base4:virtual public Base2{
public:Base4(){cout << "Base4 is constructed" << endl;}~Base4(){cout << "Base4 is destroyed" << endl;}
};//修改Derived继承方式
class Derived:public Property,public Base3,public Base4{
public:Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};
输出:
Base1 is constructed
Base2 is constructed
Property is constructed
Base3 is constructed
Base4 is constructed
Derived is constructed
Derived is destroyed
Base4 is destroyed
Base3 is destroyed
Property is destroyed
Base2 is destroyed
Base1 is destroyed
若调换Base3和Base4的继承顺序,那么Base1和Base2的构造顺序也调换
若将Property修改为虚继承,则优先构造Property
菱形继承:
继承的类具有共同的虚基类
先构造共同的虚基类,且只构造一次,再构造非虚继承的基类
析构顺序与构造相反
#include <iostream>
using namespace std;class Grand{
public:int grand;Grand(int x):grand{x}{cout << "Grand" << endl;}
};class Base1:virtual public Grand{
public:int base1;Base1(int x,int y):Grand{x},base1{y}{cout << "Base1" << endl;}
};
class Base2:virtual public Grand{
public:int base2;Base2(int x,int y):Grand{x},base2{y}{cout << "Base2" << endl;}
};
class Derived:public Base1,public Base2{
public:int derived;Derived(int x,int y,int z,int j):Grand{x},Base1{y,y},Base2{z,z},derived{j}{cout << "Derived" << endl;}
};int main(){Derived d{1, 2, 3, 4};cout << d.grand << endl;//看看到底是1,2还是3return 0;
}
输出:
Grand
Base1
Base2
Derived
1
总结:
优先按顺序构造虚基类,再顺序构造非虚基类
类的继承的构造函数写法
这里只讲比较难写的类型
背景:父类具有private成员
#include <iostream>
using namespace std;class Base{
public:Base(int x,int y):base_public{x},base_private{y}{}Base(const Base& t):base_public{t.base_public},base_private{t.base_private}{}Base& operator=(const Base& t){if(this==&t) return *this;base_public = t.base_public;base_private = t.base_private;return *this;}
public:int base_public;
private:int base_private;
};
class Derived:public Base{
public:Derived(int x, int y, int z, int j);Derived(const Derived& t);Derived& operator=(const Derived&t);
public:int derived_public;
private:int derived_private;
};Derived::Derived(int x,int y,int z,int j):Base{x,y},derived_public{z},derived_private{j}{}
1.拷贝构造函数
使用static_cast向上转换来调用基类的构造函数
Derived::Derived(const Derived& t):Base{static_cast<const Base&>(t)},derived_public{t.derived_public},derived_private{t.derived_private}
{}
2.赋值运算符
显式调用基类的赋值运算符
Derived& Derived::operator=(const Derived& t){if(this==&t)*this;Base::operator=(static_cast<const Base &>(t));derived_public = t.derived_public;derived_private = t.derived_private;return *this;
}