一 继承构造函数
是C++11中对C++98的using申明的扩展使用。
1 以前我们在子类中对父类部分的构造采用透传的方式,如下
// 一般写法
// 若父类有较多版本的构造函数,该写法比较麻烦
namespace demo1 {
struct A {
A(int a) : a_(a) {}
A(int a, const char* s) {}
int a_;
};
struct B : A {
B(int a, int b) : A(a), b_(b) {}
B(int a, const char* s, int b) : A(a, s), b_(b) {}
int b_;
};
}
2 C++11 using申明的扩展使用
// B将继承A所有构造函数
namespace demo2 {
struct A {
A(int a) : a_(a) {}
A(int a, const char* s) {}
int a_;
};
struct B : A {
using A::A; // 是隐式声明,不使用不产生真正函数代码,比透传节省空间
int b_;
};
}
3 举例,当父类构造函数有默认参数的情况
namespace demo3 {
struct A {
A(int a = 100) : a_(a) {
std::cout << "demo3 A constructor " << a_ << std::endl;
}
A(int a, const char* s) {
std::cout << "demo3 A constructor int , const char* : " << a << s << std::endl;
}
int a_;
};
struct B : A {
using A::A;
int b_;
};
}
int main() {
{
demo3::B b;
demo3::B b1(10);
demo3::B b2(50, "hello");
}
getchar();
return 0;
}
结果如下:
二 引发的问题
1 子类新增的成员如何初始化
例如demo2中的 b_ 如何初始化?可以采用C++11就地初始化的方式(=或者{}进行初始化),如下:
struct B : A {
using A::A;
int b_{50};
};
2 多继承可能导致的继承构造函数冲突问题
namespace demo4 {
struct A {
A() {}
A(int a) : a_(a) {}
int a_;
};
struct B {
B() {}
B(int b) : b_(b) {}
int b_;
};
struct C : A, B {
using A::A;
using B::B;
C(int c) {}
};
}
可以通过显式定义冲突的继承构造函数解决。
三 注意点
《深入理解C++11》
不适合基类构造函数是私有或者虚继承场景;
使用了继承构造函数,编译器不会再生成默认构造函数;