方法一:
可以使用static_cast
基类来初始化派生类,但这会导致派生对象不完整。
资源
static_cast 可以执行指向相关类的指针之间的转换,不仅可以从派生类到其基类,还可以从基类到其派生类。这确保了如果转换了正确的对象,至少类是兼容的,但是在运行时不执行安全检查来检查正在转换的对象是否实际上是目标类型的完整对象。因此,由程序员来确保转换是安全的。
看这个例子:
这里我们编写了一个基类,它有一个名为“bInt”的公共变量
class B {
public:
int bInt;
};
在这里,我们创建了一个子类,它也有自己的变量“dInt”
class D: public B {
public:
int dInt;
};
这里我们有一个基类的新实例。我们初始化基础对象的变量。
B * baseObj = new B;
baseObj->bInt = 1;
这里我们使用基类来声明和初始化派生类static_cast
。注意,此时,*derivedObj
是不完整的。具体来说,derivedObj->dInt
具有未定义的值。
D * derivedObj = static_cast<D*>(baseObj);
因为 D 是从 B 派生的,所以它也有bInt
变量。并且因为我们曾经static_cast
初始化*derivedObj
,所以它的bInt
值也和*baseObj
's一样bInt
,所以它们是相等的。
if(baseObj->bInt == derivedObj->bInt)
{
display("it's equal");
}
但是因为基类没有dInt
变量,这个变量将保持未初始化并且这个过程的结果是未定义的。
int myNum = derivedObj->dInt;
如果您打算使用 static_cast,请务必初始化派生类的成员。无论如何,这样做是一个好习惯。
使用 static_cast 时,不需要知道 B 的所有成员。D 自动拥有 B 的所有成员值。但是您尝试做的事情很危险,因为您正在创建一个不完整的对象。
方法2:如果你真的需要子类B,那么将D的构造函数编写为一个接受B *并通过复制初始化它的B:
D(const B &pass) : B(pass)
因此,当您要声明和初始化 D 类型的对象时,您就是这样做的。
B *baseObj = new B;
D *derivedObj = new D(*baseObj);
所以总而言之,你有两个选择:
- 子类 B 并使用 static_cast 初始化 D。确保初始化 D 的成员变量。
- 子类 B 并编写一个构造函数,该构造函数接受 B 并将其传递给 B 的复制构造函数。
这两种方法具有相同的结果,不同之处在于程序如何在幕后执行此操作。
不幸的是,在您的示例中,使用d=b
是“非法的”(?),因为您试图将基类分配给派生类。您只能以其他方式使用赋值运算符,例如已初始化的b=d
给定。d
您也可以编写自己的赋值运算符来执行此操作,但我个人不建议这样做。