C++11继承构造函数的使用解读
1.问题描述
在继承体系中,如果派生类想要使用基类的构造函数,必须在构造函数中显式声明。
例如:
struct A { A(int i){} }; struct B:A { B(int i):A(i){} };
这里B是从A派生出来的,B
在构造函数中依次调用A的构造函数。这样就完成了构造函数的传递。
另一个例子如下。当B中有成员变量时:
struct A { A(int i){} }; struct B:A { B(int i):A(i),d(i){} int d; };
现在从A派生的结构体B包含成员变量。当我们初始化基类A的时候,我们也初始化了元素d。现在的问题是:如果基类用于许多不同版本号的构造函数。这样,按照上面的思路,派生类中就必须写很多相应的“透传”构造函数。例如: struct A { A(int i) {} A(double d,int i){} A(float f,int i, const char* c){} //...数组的构造函数版本等. 否。};结构 B:A { B(int i):A(i){} B(double d,int i):A(d,i){} B(flat f,int i,const char* c) :A( f,i,e){} //...和基类构造函数对应的构造函数一样多};
很明显,当基类构造函数有多个时,派生类构造函数的写法看起来很麻烦而且很不切实际。
2. 问题的解答
我们可以利用定理来简化这个问题。我们来看一个例子
struct Base { void f(double i){ cout<<"Base:"<<i<<endl; } }; struct Drived:Base { using Base::f; void f(int i){ cout<<"Drived:"<<i<<endl; } };
在代码中,基类和派生类都声明了同名的函数f。但是,派生类中的方法的版本号与基类不同。这里使用Using语句表示在派生类中也使用基类版本号的函数f。这样,派生类将具有 f 函数的两个版本号。这里需要说明的是,如果不使用use语句从父类继承同名函数,则派生类中定义的f函数会屏蔽父类的f函数。当然,如果派生类根本没有定义同名的f函数。您还将选择对基类使用 f 函数。
通过这种方法,我们还可以迁移到构造函数继承。也就是说,派生类可以通过use语句声明子类要继承基类的所有构造函数。例如: struct A { A(int i) {} A(double d,int i){} A(float f,int i, const char* c){} //...数组的构造函数版本等。 不。 };结构 B:A { 使用 A::A; //关于声明中基类的各个构造函数的继承 //... };
现在,通过使用 A::A 进行声明。将基类中的所有构造函数继承到派生类。更巧妙的是,这是隐式声明为继承的。也就是说,如果继承的构造函数没有被相关代码使用,编译器就不会为其生成真正的函数代码,这比透明地传递基类的不同构造函数更节省目标代码空间。但此时还有一个问题:
当你使用use语句继承基类构造函数时。派生类无法初始化由类本身定义的新类成员。我们可以使用类成员的初始化表达式为派生类成员指定一个默认的初始值。例如:
struct A { A(int i) {} A(double d,int i){} A(float f,int i,const char* c){} //...等等系列的构造函数版本号 }; struct B:A { using A::A; int d{0}; };
注:
1。对于继承的构造函数,参数的默认值不会被继承,默认值会导致基类生成多个构造函数版本号(即参数从后向前递减。直到无参构造函数包含(当然假设也包含默认的复制构造函数),这些函数版本号由派生类继承
2.继承构造函数中的冲突管理:当派生类有多个基类时,有有些构造函数在多个基类中会导致派生类中继承的构造函数的函数名
参数相同,那么继承类中继承的构造函数就会导致非法的派生类代码,例如:
struct A { A(int){} }; struct B { B(int){} }; struct C:A,B { using A::A; using B::B; };
这会导致派生类中继承的构造函数发生冲突,解决方案是显示 确定继承类的冲突构造函数 防止隐式生成相应的继承构造函数以避免冲突。
struct C:A,B { using A::A; using B::B; C(int){} };
3。如果基类的构造函数被声明为私有构造函数或者派生类虚拟继承自基类,那么继承的构造函数就不能在派生类中声明。
4。假设当使用继承的构造函数时,编译器不会为派生类生成默认构造函数。这样我们就得考虑是否有必要继承构造函数的无参版本号。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。