C++ cannot convert from base A to derived type B via virtual base A
我有三门课:
1 2 3 4 5 6 | class A {}; class B : virtual public A {}; class C : virtual public A {}; class D: public B, public C {}; |
尝试从A*到B*的静态强制转换时,我得到以下错误:
1 | cannot convert from base A to derived type B via virtual base A |
为了理解投射系统,您需要深入到对象模型中。
简单层次模型的经典表示是包容:如果
在这个模型中,向下转换是一个简单的指针操作,通过编译时已知的偏移量进行,偏移量取决于EDOCX1的内存布局(5)。
静态强制转换就是这样做的:静态强制转换被称为静态强制转换,因为强制转换所需的计算是在编译时完成的,无论是指针算术还是转换(*)。
然而,当
因此,在编译时不可能推导出必要的指针算法:它取决于对象的运行时类型。
每当存在运行时类型依赖关系时,您都需要RTTI(运行时类型信息),使用RTTI进行强制转换是动态强制转换的工作。
综上所述:
- 编译时下降:
static_cast 。 - 运行时间下降:
dynamic_cast 。
另外两个也是编译时的类型转换,但是它们非常具体,所以很容易记住它们的用途…而且它们很臭,所以无论如何最好不要使用它们。
(*)正如@curiousguy在评论中所指出的,这只适用于下推。
据我所知,你需要使用
在这种情况下,不能使用
根据标准文件,
第5.2.9-9节,静态铸造,
An rvalue of type"pointer to cv1 B," where B is a class type, can be converted to an rvalue of type"pointer to cv2
D," where D is a class derived (clause 10) from B, if a valid standard conversion from"pointer to D" to"pointer to B"
exists (4.10), cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class
of D nor a base class of a virtual base class of D.
因此,这是不可能的,您应该使用
是的,您必须使用动态类型转换,但是您必须使基类成为多态的,例如通过添加虚拟DTOR。
我不知道这是否"安全",但是。
假设
B源于A(和纯虚拟)
因为我知道指向b的指针仍然是指向b的指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class A { virtual void doSomething(const void* p) const =0; }; class B { public: int value; virtual void doSomething(const void*p)const { const B * other = reinterpret_cast<const B*>(p); cout<<"hello!"<< other->value <<endl; } }; int main() { B foo(1),bar(2); A * p = &foo, q=&bar; p->doSomething(q); return 0; } |
此程序执行并正确返回打印"你好!"以及其他对象的值(在本例中为"2")。
顺便说一下,我所做的是高度不安全的(我个人给每个类一个不同的ID,在重新解释了强制转换后,我断言当前ID等于其他ID,以确保我们用两个相同的类做了一些事情),正如您所见,我将自己局限于"const"方法。因此,这将适用于"非常量"方法,但是如果您做了错误的事情,捕获该bug几乎是不可行的。即使有断言,40亿人中有1人有机会成功断言,即使它应该失败。(断言(id==other->id);)
顺便说一句。。一个好的OO设计不应该需要这样的东西,但是在我的例子中,我试图重构/重新设计代码,而不能放弃对reinterpret casting的使用。一般来说,你可以避免这种事情。
$5.2.9/2-"An expression e can be
explicitly converted to a type T using
a static_cast of the form
static_cast(e) if the declaration
"T t(e);" is well-formed, for some
invented temporary variable t (8.5)."
在您的代码中,您正尝试使用"t=b*"和"e=a*"进行静态u强制转换。
现在'b*t(a*)在C++中不是很好地形成(但是‘a*t(b*)’是因为‘a’是一个虚拟的明确的和可访问的‘b’基。因此,代码给出了错误。