继承方式
public:公有继承;protected:保护继承;private:私有继承。
格式:class 子类 :继承方式 父类
先写一个父类
class Father
{
public:
int a;
protected:
int b;
private:
int c;
};
再写三个继承方式不同的子类
class Son1:public Father//公有继承
{
};
class Son2:protected Father//保护继承
{
};
class Son3:private Father//私有继承
{
};
此时,Son1,Son2,Son3都继承了父类的三个整型数据成员a,b,c。
区别是:Son1中a是public,b是protected,c是private,简单来说就是保持不变;
Son2中a和b是protected,c是private;
Son3中a,b,c都是private;
接下来在主函数中运行:
因为是s1的数据成员a是public,可以类外访问;其他的不是protected就是private,因此他们在类外不能访问。
protected和private相同点:封装上都是类内可访问,类外不可访问;
不同点就是上面继承的区别。
继承的构造函数和析构函数的顺序
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout << "父类构造函数的调用" << endl;
}
~Father()
{
cout << "父类析构函数的调用" << endl;
}
};
class Son : public Father
{
public:
Son()
{
cout << "子类构造函数的调用" << endl;
}
~Son()
{
cout << "子类析构函数的调用" << endl;
}
};
int main()
{
Son s1;
}
运行结果:
结果说明,先调用父类的构造函数,在调用子类的构造函数;先调用子类的析构函数,在调用父类的析构函数。
简单说,先有爸爸再有儿子,先消儿子再消爸爸。
继承同名的处理方式
class Father
{
public:
int a = 2;
};
class Son : public Father
{
public:
int a = 3;
};
int main()
{
Son s1;
cout << s1.a;
}
当Father和Son同时有相同的数据成员或成员函数,访问子类的数据成员或成员函数时就只会访问到子类。因此,输出结果为3。
那如果想访问父类的数据成员或成员函数,则需要加入作用域。
int main()
{
Son s1;
cout << s1.Father::a;
}
则此时输出结果为2。
多继承
格式:class 子类:继承方式 父类1,继承方式 父类2,继承方式 父类3......
很简单,注意一点,若出现继承同名的情况,加上作用域即可。
class Father1
{
public:
int a = 2;
};
class Father2
{
public:
int a = 3;
};
class Son : public Father1, public Father2
{
};
此时因为两个父类都有相同的数据成员,则Son::a不明确。纠正:
int main()
{
Son s1;
cout << s1.Father1::a;//当然Father2也可
}
菱形继承
菱形继承指一个爷爷类,两个爸爸类,一个儿子类
class GrandFather
{
public:
int a = 1;
};
class Father1 : public GrandFather
{
};
class Father2 : public GrandFather
{
};
class Son : public Father1, public Father2
{
};
同样,我们也不能直接访问Son::a。
因为,Father1和Father2同时继承了GrandFather,数据一样却不共用,因此Son::a是不明确的。
解决方法:
1、用上面的同名的处理方式,加作用域;
2、将GrandFather变成一个虚基类,
格式:class 子类 : virtual 继承方式 父类
class GrandFather
{
public:
int a = 1;
};
class Father1 :virtual public GrandFather
{
};
class Father2 :virtual public GrandFather
{
};
class Son : public Father1, public Father2
{
};
int main()
{
Son s1;
cout << s1.a;
}
此时,Father1,Father2,Son都公用GrandFather中的数据成员a,s1.a,s1.Father1::a,s1.Father2::a都是一样的,一个改了其他都会改,就是共用。
小结
就这样,睡。