C++11继承构造函数在类中的使用

概念

继承构造函数在C++11特性中随之提及,其大概可以理解为:
解决了派生类无法直接使用基类中的构造函数的这一问题
正常情况下,基类定义了自己的构造函数,派生类公有继承基类后,由于派生类隐藏了基类的同名函数,是无法直接使用基类的同名函数的(这里针对于普通函数)。如下所示的例子:
基类Base的定义

class Base
{
public:
	Base(int a):m_a(a) {}
	Base(int a, double b):m_a(a),m_b(b) {}
	Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}
private:
	int m_a;
	double m_b;
	string m_c;
};

派生类Derived

class Derived :public Base 
{
public:
	
private:

};

上述的派生类Derived 中没有定义自己的构造函数,虽然是公有继承的基类Base,但是不能直接使用基类的构造函数构造自己的对象。像下面这样是错误的,无法编译通过:
在主函数中的使用:

int main()
{
	Derived d(12,4.56,"");//编译报错,没有相应的构造函数
}

衍生问题

上述也引发一个问题,若是像下面这样写,也是不正确的。

int main()
{
	Derived d;//编译报错,尝试引用已删除的函数
}

Derived 类中没有写任何函数,直接使用派生类默认的构造函数。按理这里应该是会调用自己的默认构造函数,但编译报错:尝试引用已删除的函数。这是因为派生类继承基类之后,会将派生类默认生成的构造函数删除吗?求解!!!
原因:Derived 类创建对象d时,先调用基类构造函数,再调用派生类构造函数,基类中已经显式的定义了三个有参构造函数,系统会将默认的无参构造函数删除,所以创建Derived 对象d的时候,调用基类构造函数,没有找到匹配的无参构造函数,已经被系统删除了。
但是改为下面这样:

int main()
{
	Derived d();//编译通过,但有警告:未调用原型函数(是否是有意用变量定义的?)
}

这是为什么呢????
原因:单独将Derived d();当作一个函数的声明。
同样如果是一个没有继承关系的类,可以这样创建类对象:

class Base
{
public:
private:
};

int main()
{
	Base d();//编译通过,这里也可以这样写 Base d;同样也会编译通过
}

创建对象时,调用的默认的无参构造函数。编译器会为没有显示创建构造函数,析构函数,拷贝构造函数(复制构造函数)以及赋值构造函数(赋值运算符重载)的类自动生成这些函数。

使用示例

下面是继承构造函数的使用。也就是派生类可以调用基类的构造函数的来创建自己的对象的方式。
依旧是最初的例子:

class Base
{
public:
	Base(int a):m_a(a) {}
	Base(int a, double b):m_a(a),m_b(b) {}
	Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}
private:
	int m_a;
	double m_b;
	string m_c;
};

class Derived :public Base 
{
public:
	using Base::Base;//使用基类的构造函数
private:

};
int main()
{
	//使用基类的构造函数
	Derived d(12,4.56,"");
	Derived e(2);
	Derived f(4,5.67);
}

此例中派生类可以使用基类的构造函数来创建对象。方法是在派生类中采用using 声明的方式。
像该例中的using Base::Base;使用时就是:
using 类名::函数名;

注意

以上继承构造函数在使用时,若是派生类中定义了自己的成员变量,继承构造函数不会去初始化派生类定义的成员变量。且上述using 类名::函数名; 调用基类构造函数的方法也适用于函数。

扩展使用(函数)

上面提到这种using声明的方式也可以在函数上使用,下面便是一个示例。

示例代码

依旧采用文章中提到的示例代码稍作修改。

#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
	Base(int a):m_a(a) {}
	Base(int a, double b):m_a(a),m_b(b) {}
	Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}

	void Fun() { cout << "Base::Fun()" << endl; }

private:
	int m_a;
	double m_b;
	string m_c;
};

class Derived :public Base 
{
public:
	using Base::Base;//使用基类的构造函数

	void Fun(int a) { cout << "Derived::Fun()" << endl; }//隐藏
private:

};

int main()
{
	//使用基类的构造函数
	Derived d(12,4.56,"");
	Derived e(2);
	Derived f(4,5.67);

	//使用基类的函数
	d.Fun();
}

可以看到在使用继承构造函数的基础上,在基类和派生类中新增了函数Fun,两个函数分别位于基类与派生类中,函数名相同,参数不同,此为隐藏关系。更多关于隐藏的介绍可以查看我之前的博文,搜索关键字——隐藏
这里通过d.Fun()调用父类的函数Fun(),但是整个代码是无法通过编译的,要想通过派生类对象调用父类的同名函数需要使用相应的using 类名::函数名来声明
下面稍作修改,是正确的代码:

#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
	Base(int a):m_a(a) {}
	Base(int a, double b):m_a(a),m_b(b) {}
	Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}

	void Fun() { cout << "Base::Fun()" << endl; }

private:
	int m_a;
	double m_b;
	string m_c;
};

class Derived :public Base 
{
public:
	using Base::Base;//使用基类的构造函数
	using Base::Fun;//使用基类的同名函数
	
	void Fun(int a) { cout << "Derived::Fun()" << endl; }//隐藏
private:

};

int main()
{
	//使用基类的构造函数
	Derived d(12,4.56,"");
	Derived e(2);
	Derived f(4,5.67);

	//使用基类的函数
	d.Fun();
	d.Base::Fun();//与上一行写法都可以,有两种调用方式
	
	e.Fun(2);//使用派生类自己的函数
}

上述代码可以编译通过。

输出结果

输出结果为:
在这里插入图片描述

注意

在派生类中引入using声明之后,d.Fun();与d.Base::Fun();都可以达到调用基类的Fun()函数的作用。
在没有引入using声明时,可以采用d.Base::Fun();这种调用方式。d.Base::Fun();的调用已经指明了调用的是基类中的函数。
下面是不引入using声明的基类同名函数Fun()调用示例:

#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
	Base(int a):m_a(a) {}
	Base(int a, double b):m_a(a),m_b(b) {}
	Base(int a, double b, string c) :m_a(a), m_b(b), m_c(c) {}

	void Fun() { cout << "Base::Fun()" << endl; }

private:
	int m_a;
	double m_b;
	string m_c;
};

class Derived :public Base 
{
public:
	using Base::Base;//使用基类的构造函数

	void Fun(int a) { cout << "Derived::Fun()" << endl; }//隐藏
private:

};

int main()
{
	//使用基类的构造函数
	Derived d(12,4.56,"");
	Derived e(2);
	Derived f(4,5.67);

	//使用基类的函数
	d.Base::Fun();//编译正确
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肩上风骋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值