通过另一个派生 class 的对象初始化派生 class 的基础部分的构造函数
Constructor to initialize base part of derived class by object of another derived class
假设我有一个基数 class 和 2 个派生的 classes:
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
+ 基础 class 初始化列表中的复制构造函数的指针:
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));
首先调用Base
的默认构造函数,然后初始化每个成员:
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) { }
- Pointer to Derived1 + dynamic_cast + base class copy-constructor within initializer list
不需要指针,不需要动态转换,也不需要将参数限制为仅 Derived1
.
- Reference to Base and cast Derived1 when calling
这很好,除了强制转换是多余的。对象可以隐式转换为其基数。
- Call default constructor of Base first and then initialize every single member
这毫无意义地复杂化,并且在 base 不是默认可初始化的情况下不是一个选项。
另一种方法是按值传递基数,然后从中移动:
Derived2(Base base) : Base(std::move(base))
这允许避免从右值参数复制。这对于示例中的琐碎 Base
不是特别有用,但对于一些复制速度较慢的真实示例可能会快得多。
假设我有一个基数 class 和 2 个派生的 classes:
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
+ 基础 class 初始化列表中的复制构造函数的指针: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));
首先调用
Base
的默认构造函数,然后初始化每个成员: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) { }
- Pointer to Derived1 + dynamic_cast + base class copy-constructor within initializer list
不需要指针,不需要动态转换,也不需要将参数限制为仅 Derived1
.
- Reference to Base and cast Derived1 when calling
这很好,除了强制转换是多余的。对象可以隐式转换为其基数。
- Call default constructor of Base first and then initialize every single member
这毫无意义地复杂化,并且在 base 不是默认可初始化的情况下不是一个选项。
另一种方法是按值传递基数,然后从中移动:
Derived2(Base base) : Base(std::move(base))
这允许避免从右值参数复制。这对于示例中的琐碎 Base
不是特别有用,但对于一些复制速度较慢的真实示例可能会快得多。