继承引出的对构造方法的要求
继承引出的对构造方法的要求
构造方法是类的一个特殊成员,它会在实例化对象时被自动调用。我们无法使用对象来调用构造函数,因为在构造函数构造出对象之前,对象是不存在的。因此构造函数被用来创建对象,而不能通过对象来调用。
那么我们都知道继承,继承由于派生类继承基类内成员(无法继承构造方法,继承了私有成员,只是无法直接访问),我派生类可以调用基类的成员,那么我派生类肯定要知道基类是如何对自己数据进行初始化的。那么这提出了第一个要求。
- 派生类一定会调用基类的构造方法。
以C++代码为例,假设我们现在有两个类,基类Person,派生类Student
class Person {
public:
// constructor with argument
Person(int x) {
cout << "Person Constructor with " << x << endl;
}
};
class Student:public Person {
public:
// default constructor without argument
Student() {
cout << "Student Default Constructor" << endl;
}
};
int main (){
Student a;
}
我们看上面的代码,基类没有无参构造方法,派生类有。我们知道主函数中 Student a 这行代码会隐性调用Student类中默认的无参构造方法。同时,刚刚学到的,也肯定会调用基类Person中的构造方法。但是,这里的代码没有指定会调用基类哪一个构造方法,所以就会调用基类Person默认的无参构造方法。
可是,基类Person没有无参构造方法啊!!!所以这个程序编译器的确会报错,这也就提出了下一个要求。
- 一定要设计至少2个构造方法,包含1个有参数的构造方法用于初始化成员变量和1个无参数的构造方法设定默认情况。
于是,我们修改代码,
class Person {
public:
// default constructor
Person() {
cout << "Person Default Constructor" << endl;
}
// constructor with argument
Person(int x) {
cout << "Person Constructor with " << x << endl;
}
};
class Student:public Person {
public:
// default constructor
Student() {
cout << "Student Default Constructor" << endl;
}
// constructor with argument
Student(int y) {
cout << "Student Constructor with " << y << endl;
}
};
int main(){
Student a;
return 0;
}
/*
Output
Person Default Constructor
Student Default Constructor
*/
这样,程序就正常运行了。由于我们是调用了派生类的默认无参构造方法,同样也调用了基类的无参构造方法。
我们可以看到,是先调用了基类的构造方法再调用了派生类的构造方法,符合人们的认知。或者你可以这么想,我是我父母的孩子,我身上的DNA来自于他们,我不得先知道他们的DNA是啥才行吗?所以创建派生类对象时会先调用基类的构造方法。
那么问题来了,我的派生类的构造方法,想显式地调用基类别的构造方法,可以吗?
当然是可以的。
class Person {
public:
Person() {
cout << "Person Default Constructor" << endl;
}
Person(int x) {
cout << "Person Constructor with " << x << endl;
}
};
class Student:public Person {
public:
// 调用父类中带参的构造方法
Student() : Person(10) {
cout << "Student Default Constructor" << endl;
}
// 同样调用父类中带参的构造方法
Student(int y) : Person(y) {
cout << "Student Constructor with " << y << endl;
}
};
int main(){
Student a(20);
return 0;
}
/*
Output
Person Constructor with 20
Student Constructor with 20
*/
- 派生类可以指定调用指定的基类构造方法。如果基类的构造方法是无参的,那么在派生类中写不写都可以,不写的话会隐式地调用。