我试图找出一种方法,在一些困难的条件下将子类的实例动态地转换为它的父类。
具体来说,我有一个看起来像这样的对象层次结构(我已经简化了很多,所以如果有些东西没有意义,可能是由于简化了):
class Object {
public:
virtual ~Object() {}
};
// shown just to give an idea of how Object is used
class IntObject: public Object {
protected:
int value;
public:
IntObject(int v) { value = v; }
int getValue() { return value; }
};
template <class T>
class ObjectProxy: public Object {
protected:
T *instance;
public:
ObjectProxy(T *instance): instance(instance) {}
T *getInstance() { return instance; }
};
该类ObjectProxy
本质上充当包装器,以允许在Object
层次结构中使用其他类型。具体来说,它允许保留指向类实例的指针,并在稍后调用实例的方法时使用。例如,假设我有:
class Parent {
protected:
int a;
public:
Parent(int v) { a = v; }
virtual ~Parent() {}
void setA(int v) { a = v; }
int getA() { return a; }
};
class Child: public Parent {
protected:
int b;
public:
Child(int v1, int v2): Parent(v1) { b = v2; }
void setA(int v) { b = v; }
int getB() { return b; }
};
我可能会在以下情况下使用它们:
template <typename C>
void callFn(std::list<Object *> &stack, std::function<void (C*)> fn) {
Object *value = stack.front();
stack.pop_front();
ObjectProxy<C> *proxy = dynamic_cast<ObjectProxy<C> *>(value);
if (proxy == nullptr) {
throw std::runtime_error("dynamic cast failed");
}
fn(proxy->getInstance());
}
void doSomething(Parent *parent) {
std::cout << "got: " << parent->getA() << std::endl;
}
int main() {
std::list<Object *> stack;
// this works
stack.push_back(new ObjectProxy<Child>(new Child(1, 2)));
callFn<Child>(stack, doSomething);
// this will fail (can't dynamically cast ObjectProxy<Child> to ObjectProxy<Parent>)
stack.push_back(new ObjectProxy<Child>(new Child(1, 2)));
callFn<Parent>(stack, doSomething);
}
如上述注释中所述,此代码由于已知原因而失败。在示例代码中,很容易避免调用callFn<Parent>(stack, doSomething)
. 但是,在我的真实代码中,我使用函数的签名来确定类型,如果它是父类的方法,它将自动用于模板参数。
我的问题是是否有任何方法可以从 ObjectProxy 类型的对象中实现动态转换。部分复杂性来自这样一个事实,即在 functioncallFn
中,您只有 Parent 类型,而没有 child 类型。
我研究过使用类型擦除boost::any
(即ObjectProxy
停止模板化,而是使用),但在动态转换(是静态boost::any instance
的)时仍然遇到问题。boost::any_cast
我确实找到了dynamic_any
关于 SO 的提及,但还没有让它正常工作。
非常感谢您对问题的任何帮助或见解。