19.10、C++11新特性有哪些⑩【继承构造函数】
当需要在子类中初始化父类的变量时(也就是在子类中调用父类的构造函数),我们不需要一个一个地委托父类的构造函数,而是直接使用继承构造函数即可:
using Base::Base //base时父类的名字
使用继承构造函数,就表示在子类中调用父类的构造函数(公有的),按照父类构造函数的方式初始化父类的变量
- 不使用继承构造函数:
class TestA {
public:
TestA(string i): a1(i) {}
TestA(int i) : a2(i) {}
TestA(double i) : a3(i) {}
~TestA() {}
string geta1() {
return a1;
}
virtual string getb1() = 0;
private:
string a1;
int a2;
double a3;
};
class TestB: public TestA{
public:
//一个一个写
TestB(string i):TestA(i),b1(i) {}
TestB(int i) :TestA(i), b2(i) {}
TestB(double i) :TestA(i), b3(i) {}
~TestB() {}
virtual string getb1() override {
return b1;
}
virtual void testb();
private:
string b1;
int b2;
double b3;
};
- 使用继承构造函数:
class TestA {
public:
TestA(string i): a1(i) {}
TestA(int i) : a2(i) {}
TestA(double i) : a3(i) {}
~TestA() {}
string geta1() {
return a1;
}
virtual string getb1() = 0;
private:
string a1;
int a2;
double a3;
};
class TestB: public TestA{
public:
// 继承构造函数
using TestA::TestA; //直接调用TestA中的构造函数
// ....
virtual void testb();
private:
string b1;
int b2;
double b3;
};
-
其实继承构造函数本质上就是 在子类中初始化父类的变量,所以它并不能初始化子类自己的变量。那使用继承构造函数之后,子类如何初始化自己的变量呢?
- 直接就地初始化(针对非静态成员变量),即 = 或 { }
class Derived: public Base {
public:
// 使用继承构造函数
using Base::Base;
// 假设派生类只是添加了一个普通的函数
void display() {
// do something
}
private:
// 派生类新增数据成员
double _double{0.0}; //直接用{}
};
- 用子类的构造函数初始化,在初始化列表中初始化(没有第一种简洁)
class Derived :public Base {
public:
// 使用继承构造函数
using Base::Base;
// 新增派生类构造函数
Derived(int a, double b):Base(a), _double(b){}//在初始化列表中初始化
// 假设派生类只是添加了一个普通的函数
void display() {
// do something
}
private:
// 派生类新增数据成员
double _double{0.0};//本地初始化 会被初始化列表 覆盖
};
- 注意,当基类的构造函数由默认值时,子类的构造函数不会继承这个默认值,同时会产生多个版本的几倍构造函数:
class A {
public:
A(int a = 3, double b = 4): _a(a), _b(b){}
void display() {
cout<<_a<<" "<<_b<<endl;
}
private:
int _a;
double _b;
};
class B:public A {
public:
using A::A;
};
/*
A中的构造函数有下面这几个版本:
A()
A(int)
A(int, double)
A(const A&)
B中的继承构造函数有下面这几个版本
B()
B(int)
B(int, double)
B(const B&) */