我在ARM7嵌入式环境中工作。我使用的编译器不支持完整的C ++功能。它不支持的一个功能是动态类型转换。
有没有办法实施dynamic_cast<>()
?
我使用Google查找代码,但到目前为止还没有运气。有任何想法吗?有链接吗?
更新:
由于评论......我正在使用ARM(R)IAR C / C ++编译器。
答案 0 :(得分:3)
dynamic_cast在离开基类时很有用,尽可能少地完成。
假设您想要执行此操作的实例是有限的,那么基类中的GetMessageType()
等虚函数会在每个派生类中返回不同的值,这将让您知道static_cast的内容。
答案 1 :(得分:2)
看一下COM概念 - 对象有一个方法可以返回指向特定接口的指针,该接口由未编译到编译器中的标识符选择(在COM的情况下,是UUID)。
根据您的应用程序,可以使用简单的整数:
class castable {
virtual bool cast_to(int desttype) = 0;
};
class type1 : public castable { public: static int const type = 1; };
class type2 : public castable { public: static int const type = 2; };
class impl : public type1, public type2 {
virtual void *cast_to(int desttype) {
switch(desttype) {
case type1::type: return static_cast<type1 *>(this);
case type2::type: return static_cast<type2 *>(this);
default: return 0;
}
}
};
然后,如果模板正常工作:
template<typename T> T my_dynamic_cast(castable *obj) {
return reinterpret_cast<T>(obj.cast_to(T::type));
}
然后,您可以正常创建对象,并在基类指针之间进行转换:
impl im;
type1 *t1 = &im; // Implicit, as it is a base class
type2 *t2 = my_dynamic_cast<type2 *>(t1);
这里唯一的困难是分配标识符。
答案 2 :(得分:1)
这实际上取决于您需要多少dynamic_cast
功能。
通常情况下,我看到dynamic_cast
用于执行检查转化:如果最终dynamic_cast<Derived*>(p)
实际类型不是0
,p
将返回Derived*
。
......但即使这很复杂:
p
真的是EvenMoreDerived
而不只是Derived
怎么办?p
多次从Base
继承?它可以变得更加毛茸茸:
static_cast
无法越过virtual
继承边界。static_cast
不适合跨分支转换(您必须通过共同的祖先)static_cast
无法模拟dynamic_cast<void*>()
转化。因此,如果您希望在没有virtual
的情况下进行单继承的情况下检查转换的简单准系统继承树,那么您实际上可以在用户域中实现它
否则,如果没有RTTI支持,您将会陷入困境。
简单(哑?)实现的示例,从类层次结构的支持开始:
class Base {
public:
typedef size_t ID;
virtual ID getID() const = 0;
protected:
static ID NextID() { static ID = 0; return ID++; }
// much more stuff
};
class Derived: public Base {
public:
static ID GetID() { static ID id = Base::NextID(); return id; }
virtual ID getID() const { return GetID(); }
};
我们可以利用它:
template <typename To>
To* dyn_cast(Base* b) {
if (b and b->getID() == To::GetID()) { return static_cast<To*>(b); }
return 0;
}
但是,这仅适用于一个级别。因此,如果MoreDerived
继承自Derived
,那么:
MoreDerived md;
assert(dyn_cast<Derived>(&md)); // failure ...
所以这里真的很棘手。
一种可能的方法是从层次结构的顶部检查到底部。
class Base {
public:
template <typename To>
bool isa() const {
return this->match(To::GetID());
}
protected:
typedef size_t ID;
static ID NextID() { static ID id = 0; return id++; }
virtual bool match(ID) const { return false; }
};
class Derived: public Base {
public:
static ID GetID() { static ID id = NextID(); return id; }
protected:
virtual bool match(ID id) const { return id == GetID() || Base::match(id); }
};
class MostDerived: public Derived {
public:
static ID GetID() { static ID id = NextID(); return id; }
protected:
virtual bool match(ID id) const { return id == GetID() || Derived::match(id); }
};
略微复杂,但现在:
template <typename To, typename From>
To const* dyn_cast(From const* f) {
if (f and f->template isa<To>()) { return static_cast<To const*>(f); }
return 0;
}
template <typename To, typename From>
To* dyn_cast(From* f) { return const_cast<To*>(dyn_cast<To>((From const*)f)); }
测试用例:
int main() {
Derived derived; MostDerived mostDerived;
Base* d = &derived, * md = &mostDerived;
if (dyn_cast<Derived>(d)) { std::cout << "Derived -> Derived: ok\n"; }
else { std::cout << "Derived -> Derived: ko\n"; }
if (dyn_cast<MostDerived>(md)) { std::cout << "MostDerived -> MostDerived : ok\n"; }
else { std::cout << "MostDerived -> MostDerived : ko\n"; }
if (dyn_cast<Derived>(md)) { std::cout << "MostDerived -> Derived : ok\n"; }
else { std::cout << "MostDerived -> Derived : ko\n"; }
if (dyn_cast<MostDerived>(d)) { std::cout << "Derived -> MostDerived: ko\n"; }
else { std::cout << "Derived -> MostDerived: ok\n"; }
}
与真正的dynamic_cast
相比,它仍然非常不完整。但它应该涵盖大多数用途。
答案 3 :(得分:-1)
是否有可能只是转换指针并开始将其用作其他类型的对象?
Foo* f = new Foo();
f.baz();
Bar* b = (Bar*)f;
b.bop();