问题描述
class Base {
public:
Base() : m_base(0) { }
private:
int m_base;
};
class Derived1 : public Base {
public:
Derived1() : Base(),m_d1(1) { }
private:
int m_d1;
};
class Derived2 : public Base {
public:
Derived2(): Base(),m_d2(2.5) { }
private:
double m_d2;
};
我现在希望重载的构造函数通过Derived2
实例初始化其基础部分来构造Derived1
实例,在该实例中我遇到了一些不同的方法:
-
指向初始化器列表中的
Derived1
+dynamic_cast
+基类复制构造函数的指针:Derived2(Derived1 *d1) : Base(*(dynamic_cast<Base*>(d1))),m_d2(3.5) { }
显然,这存在取消引用无效指针的问题
-
引用
Base
并在调用时强制转换Derived1
Derived2(const Base &base) : Base(base),m_d2(3.5) { } // ... Derived1 d1 = Derived1(); Derived2 d2 = Derived2(static_cast<Base>(d1));
-
Derived2(Derived *d1) : Base(),m_d2(3.5) { if (d1) { m_base = d1->base(); } }
但这需要访问
Derived1
的成员以及Base
的成员才能成为protected
当然可以肯定还有另一种更好的方法-那么哪种是实现这一目标的最佳方法,为什么呢?
解决方法
您无需强制转换为基本类型。
您要说的话最直接的翻译是
Derived2(const Derived1& d1): Base(d1),m_d2(2.5) { }
然后您所需要的就是
Derived1 d1;
Derived2 d2(d1);
如果您要接受从Base
派生的任何类型:
Derived2(const Base& b): Base(b),m_d2(2.5) { }
,
- 初始化程序列表中指向Derived1 + dynamic_cast +基类复制构造函数的指针
不需要指针,不需要动态转换,也不需要将参数限制为Derived1
。
- 在调用时引用Base并强制转换Derived1
这很好,除了强制转换是多余的。一个对象可以隐式转换为其基。
- 首先调用Base的默认构造函数,然后初始化每个成员
这毫无意义地复杂,在无法默认初始化base的情况下,这不是选择。
另一种选择是按值传递基数,然后从基值移走:
Derived2(Base base) : Base(std::move(base))
这可以避免从rvalue参数复制。对于示例中的琐碎Base
来说,这并不是特别有用,但是对于某些慢速复制的真实示例来说,速度可能要快得多。