我知道C++不像Java或C#一样支持协变容器元素。因此,以下代码可能会导致未定义行为:
#include <vector>
struct A {};
struct B : A {};
std::vector<B*> test;
std::vector<A*>* foo = reinterpret_cast<std::vector<A*>*>(&test);
毫不意外的是,当我建议这个解决方案给另一个问题时,我收到了负评。
但是C++标准中的哪一部分确切地告诉我这会导致未定义行为?保证std::vector<A*>
和std::vector<B*>
将它们的指针存储在连续的内存块中。保证sizeof(A*) == sizeof(B*)
。最后,A* a = new B
是完全合法的。
那么除了风格之外,我召唤了标准中的哪些恶灵呢?
A
添加到foo
中,它就会处于无效状态,因为foo
保证所有元素都是类型B
。C# 也不支持这一点。C# 只支持在接口和委托中用于安全方式使用泛型参数(仅限输入或输出)。Java 支持它,因为它添加了运行时检查,并在对象基类上内部工作。 - CodesInChaosvoid append( Vector<? super Derived> v ) { v.add( new Derived() ); }
或void extract( Vector<? extends Base> v ) { Base b = v.get(0); }
,但它不会允许引用的转换。 - David Rodríguez - dribeasVector
(包含Object
)。另一方面,如果允许转换,则可以将Base
对象添加到Derived
的容器中。 - David Rodríguez - dribeas