可能你做题时会遇到这么一个问题:
子类将继承父类的全部内容。
这不肯定是错的嘛,子类只能继承父类的public和protected成员,而不能继承private成员。然后有的教材却说这句话是正确的。
其实,确实不能说这句话有错。
在C++中,有三种继承方式,分别是公有继承、私有继承、保护继承。
公有继承是父类的公有属性变成子类公有属性,父类的保护属性变成子类的保护属性,父类的私有属性并不变成子类的属性,它只能由父类访问,但它却实实在在并子类给“继承”下去了,只能无法直接访问而已。但是可以通过父类的函数来访问,父类的成员函数只能访问父类成员。看下面例子:
#include <iostream>
using namespace std;
class Father{
private:
int a
};
class Son:public{
public:
int a;
};
int main(){
cout<<sizeof(Father)<<endl;
cout<<sizeof(Son)<<endl;
return 0;
}
输出4和8
可见,子类中确实“继承”了父类的private成员。
公有继承、私有继承和保护继承对父类的私有成员的继承方员都一样。对于父类的非私有成员,保护继承把它当成了子类的保护成员,私有继承把它当成了子类私有成员,公有继承保留原样。
然后讲讲可能出现的同名问题。采用同名覆盖的原则,可以用父类名::父类成员名来访问父类的成员。在类外还可以这样访问:
Son a;
a.Father::var=3;//假设父类有一个var变量,子类也有一个var变量,要访问父类的var变量。
再来说说构造函数和析构函数。
若子类的构造函数没有显示调用父类的构造函数,则默认调用父类的无参构造函数。若父类定义了带参构造函数且没有无参构造函数,则子类必须显示调用父类的带参构造函数,否则会出错。
C++中显示调用父类的构造函数是采取构造函数初始化表的形式,如:
Son():Father(){}
最后说一下子对象,看下面例子:
class A{
public:
A(int a){}
};
class B{
public:
A a;
};
int main(){
B object;
return 0;
}
该程序实例化了一个B类对象object,它有一个类型为A的子对象a,但是类A没有无参的构造函数,而在类声明成员时又不能显示指明参数,也就是在类声明时像A a(1);这样的写法是错误的,无法通过编译,这时就必须在A的构造函数初始化表中调用子对象的构造函数,就像这样:
B():a(1){}
若有多个子对象,用逗号隔开就行。
构造函数初始化表先于构造函数体执行。
在执行派生类的析构函数时,系统会自动调用基类的析构函数和子对象的析构函数。对基类和子对象进行清理。调用的顺序与构造函数正好相反:先执行派生类自己的析构函数,对派生类新增加的成员进行清理,然后调用子对象的析构函数,对子对象进行清理,最后调用基类的析构函数,对基类进行清理。