首页 > 代码库 > C++中继承中遇到的构造函数问题

C++中继承中遇到的构造函数问题

今天在开发时遇到了一个之前一直以为理所当然的构造函数问题。
先给总结:
子类在构造时,如果没有显式调用父类的构造函数,会先调用父类的默认构造函数(无参数的)

下面给出不同情况的例子
例子一:父类有默认的构造函数,子类的构造函数随便
#include <iostream>
class Base{
public:
	Base(){
		
	}
};

class Derive:public Base{
public:
	Derive(int a,int b){
		
	}
};

int main(){
	
	Derive c(1,2);
		
	return 0;
}

结果:编译通过,暂时不能说明问题。

例子二:父类没有默认的构造函数,子类的构造函数随便
#include <iostream>
class Base{
public:
	Base(int a){
		
	}
};

class Derive:public Base{
public:
	Derive(int a,int b){
		
	}
};

int main(){
	
	Derive c(1,2);
		
	return 0;
}

结果:编译错误,错误信息:[Error] no matching function for call to ‘Base::Base()‘
说明,子类的构造需要先调用父类的默认构造函数

例子三:父类没有默认的构造函数,子类的构造函数随便,但是显式调用了父类的构造函数
#include <iostream>
class Base{
public:
	Base(int a){
		
	}
};

class Derive:public Base{
public:
	Derive(int a,int b):Base(a){
		
	}
};

int main(){
	
	Derive c(1,2);
		
	return 0;
}

结果:编译成功
说明,显式调用父类的构造函数之后,不再调用父类的默认构造函数

例子四:父类没有默认的构造函数,子类的构造函数与父类的参数列表相同,但是没有显式调用父类的构造函数
#include <iostream>
class Base{
public:
	Base(int a){
		
	}
};

class Derive:public Base{
public:
	Derive(int a){
		
	}
};

int main(){
	
	Derive c(1);
		
	return 0;
}

结果:编译错误
说明,其实这种情况跟例子二的情况是一样的,只不过父类跟子类的构造函数参数一样,所以会给人感觉子类会调用父类相同参数的构造函数,但其实子类还是先调用父类的默认构造函数的。由于父类没有默认的构造函数,所以编译错误,错误信息跟例子二一样。

例子五(陷阱):父类跟子类的构造函数有相同的参数,且父类有默认的构造函数。子类没有显式调用父类的构造函数。
#include <iostream>
class Base{
public:
	Base(int a){
		this->a = a;
	}
	Base(){
		
	}
public:
	int a;
};

class Derive:public Base{
public:
	Derive(int a){
		
	}
};

int main(){
	
	Derive c(1);
	std::cout << c.a << std::endl;
	return 0;
}

结果:编译成功,运行输出结果为:3674912
说明,这种情况跟例子四如出一辙,只不过由于父类有默认的构造函数,所以才会编译成功。子类的带一个int参数的构造函数并没有调用父类带一个int参数的构造函数。

最后,再来一次总结:上面五个例子说明了,如果子类的构造函数中没有显式调用父类的构造函数,则先默认调用父类的默认构造函数。
换句话说,在使用继承时,如果父类没有默认的构造函数,则子类的构造函数应当显式地调用父类的自定义构造函数。

C++中继承中遇到的构造函数问题