目录
5.父类中自定义了有参构造函数,子类继承时提示语法错误问题的解决
C++中子类可以继承父类中的成员,达到减少代码量的作用。此外,子类的内部也可以写上自身特殊的成员。
1.继承基本语法
下面是父类
下面是子类的写法
class 子类 :public(继承方式) 父类
2.继承方式
继承方式一共三种:
(1)公共继承;(2)私有继承;(3)保护继承
首先,父类中的private成员,子类无论用哪种继承方式都无法访问。
如果是公共继承,则子类中原父类的成员权限均不改变;
如果是保护继承,则子类中原父类的所有除private外的成员都变成protected类型;
如果是保护继承,则子类中原父类的所有除private外的成员都变成private类型。
再复习一下,一个类中的public成员,类外可以输出、修改;其它类型的成员类外不能输出、修改,简而言之就是无法访问。
3.继承后子类的内存空间
子类完全继承父类中的所有成员,因此子类的内存空间必须额外加上父类的内存空间。
4.构造子类对象时,父类和子类的构造、析构顺序
先构造父类、再构造子类,然后析构子类,最后析构父类
5.父类中自定义了有参构造函数,子类继承时提示语法错误问题的解决
#include<iostream>
using namespace std;
class Person{
public:
int age;
Person(int a){
age = a;
cout<<"父类构造函数"<<endl;
}
protected:
int height;
private:
int weight;
};
class child : public Person{
public:
int growRate;
};
int main()
{
child c1;
cout<<sizeof(c1);
return 0;
}
上面的代码在编译时会发生错误,原因是子类实例化时父类构造也会运行,而且是会无条件的调用父类无参构造。这里由于只声明了父类有参构造,C++不提供默认无参构造,因此无法构造出父类,子类就无法构造,因此报错。只需补全父类的无参构造即可。
另一个注意点是:子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。
6.父类子类中同名成员如何访问
直接写c1.age,则默认访问的是子类中的age变量,访问父类中的age变量要写成c1.Person::age。当然,对于同名函数来说,和同名变量的格式一样。注意这个时候,父类中的函数重载不能作为区分子类、父类同名函数的依据。
#include<iostream>
using namespace std;
class Person{
public:
int age;
Person(){
age = 100;
}
func(){
cout<<"Person - func() is called"<<endl;
}
func(int a){
cout<<"Person - func(int a) is called"<<endl;
}
protected:
int height;
private:
int weight;
};
class child : public Person{
public:
int age;
child(int a){
age=a;
}
func(){
cout<<"child - func() is called"<<endl;
}
};
int main()
{
child c1(1);
cout<<c1.age<<' '<<c1.Person::age<<endl;
c1.func();
c1.Person::func();
// c1.func(10);
//上面这一行报错,应该改成下面的形式
c1.Person::func(10);
return 0;
}
7.父类子类中同名静态成员如何访问
同名静态成员变量:
Son::Base::m_A也可以直接写成Base::m_A,二者结果相同,但是意义不一样。
前者意为通过子类访问其父类作用域下的m_A,后者直接访问父类作用域下的m_A。
8.多继承
9.菱形继承
为了解决菱形继承带来的问题,需要在羊驼类继承的两个父类加上virtual关键字,具体格式如下:
加上virtual之后,实际上age就保留一份,因此不再存在二义性:
虚继承的底层实现:
左边是虚继承后的对象模型,右边是之前的对象模型。
实际上,被标记为虚继承类型之后,羊类和驼类中的int m_Age消失了,取而代之的是一个虚基类指针(vbptr),这个指针指向一个虚基类表(vbtable),表中记录的是一个偏移量,这样一来,羊类下的虚基类指针指向的是指针位置加上指针记录的偏移量,最终正好是其父类中的int m_Age,驼类同理。这样就将原来的两个int变量减少到了如今的1个int变量,不过多了两个指针的占用空间(8字节)。