C++ 将基类指针强制转换为派生类(参考)

C++ 将基类指针强制转换为派生类(参考),c++,C++,我有一个类,它包含一个方法的几个重载版本。每个版本都有一个参数-对象-该对象总是从一个基类派生。没有采用基类参数的方法 class Base { ... } class Object1 : public Base { ... } class Object2 : public Base { ... } class Object3 : public Base { ... } class T { // ... do_sth(const Object1& obj);

我有一个类,它包含一个方法的几个重载版本。每个版本都有一个参数-对象-该对象总是从一个基类派生。没有采用基类参数的方法

class Base { ... }
class Object1 : public Base { ... }
class Object2 : public Base { ... }
class Object3 : public Base { ... }

class T
{
    // ... 
    do_sth(const Object1& obj);
    do_sth(const Object2& obj);
    do_sth(const Object3& obj);
    // ...
}
然后,我创建了一个向量,其中惟一的_ptr指向基类,只包含派生类对象

std::vector<std::unique_ptr<Base>> vect;    // then some push_backs

然而,这样做是不可能的,因为render*对象调用确实存在,这甚至不存在,也不是想要的行为。我试图用几种不同的铸造方法来替换这条线,但没有一种尝试成功。如何解决这个问题?

鉴于不需要修改任何对象类,也不需要注释中的虚拟函数,您的第一个解决方案似乎是动态转换,因此:

for (auto const& uObj : vect) {
    if(auto *obj = dynamic_cast<Object1 const *>(uObj.get()))
        T_obj.do_sth(*obj);
    else if(auto *obj = dynamic_cast<Object2 const *>(uObj.get()))
        T_obj.do_sth(*obj);
    else if( /* ... */)
        // And so on.
}
通常情况下,我会使用一次性宏,风险自负

#define DYNAMIC_CALL_DO_STH(Type) \
    if(auto *obj = dynamic_cast<Type const *>(uObj.get())) \
        T_obj.do_sth(*obj)

for (auto const& uObj : vect) {
    DYNAMIC_CALL_DO_STH(Object1);
    else
    DYNAMIC_CALL_DO_STH(Object2);
    else
    DYNAMIC_CALL_DO_STH(Object3);
}

#undef DYNAMIC_CALL_DO_STH

考虑到不修改任何对象类、不使用注释中的虚拟函数的要求,这里的第一个解决方案似乎是dynamic_cast,用于:

for (auto const& uObj : vect) {
    if(auto *obj = dynamic_cast<Object1 const *>(uObj.get()))
        T_obj.do_sth(*obj);
    else if(auto *obj = dynamic_cast<Object2 const *>(uObj.get()))
        T_obj.do_sth(*obj);
    else if( /* ... */)
        // And so on.
}
通常情况下,我会使用一次性宏,风险自负

#define DYNAMIC_CALL_DO_STH(Type) \
    if(auto *obj = dynamic_cast<Type const *>(uObj.get())) \
        T_obj.do_sth(*obj)

for (auto const& uObj : vect) {
    DYNAMIC_CALL_DO_STH(Object1);
    else
    DYNAMIC_CALL_DO_STH(Object2);
    else
    DYNAMIC_CALL_DO_STH(Object3);
}

#undef DYNAMIC_CALL_DO_STH

做某事和渲染的函数签名是什么?您是否按值传递对象?你能提供一个吗?你考虑过虚拟函数吗?我想你可能在这里有一个设计问题。派生类的不同功能应使用虚拟函数实现,而不是使用不同的外部函数。当你写目标时,做某事;反对;,被调用的专门化是在编译时确定的,因此将把参数当作一个基来处理&不管它的运行时类型如何。@mdjdrn1在这个问题中,您可能想扩展虚拟函数不适合的原因。这种情况可能有很多种方式,但就代码复杂度和大小而言,它们是最轻的。是的,似乎虚拟函数是避免混乱的最佳选择。do_sth和render的函数签名是什么?您是否按值传递对象?你能提供一个吗?你考虑过虚拟函数吗?我想你可能在这里有一个设计问题。派生类的不同功能应使用虚拟函数实现,而不是使用不同的外部函数。当你写目标时,做某事;反对;,被调用的专门化是在编译时确定的,因此将把参数当作一个基来处理&不管它的运行时类型如何。@mdjdrn1在这个问题中,您可能想扩展虚拟函数不适合的原因。可能有很多方法都是这样,但是关于代码复杂度和大小,它们是最轻的。是的,似乎虚拟函数是避免这里混乱的最佳选择。如果这是解决我的问题的唯一方法,没有虚拟方法,那么现在我看到这个解决方案只适用于我项目的当前结构。添加任何新的派生类都需要在该循环中进行修改。如果dou_sth是虚拟函数,我可以用基于范围的for循环调用它。-简单得多。感谢您的回答。@mdjdrn1您已经指出了虚拟函数的所有优点和缺点;如果您可以费心在一个地方维护一个派生类列表,那么当然也可以使用一些宏+模板技巧来生成代码。如果这是在没有虚拟方法的情况下解决我的问题的唯一方法,那么现在我看到这个解决方案只适用于我项目的当前结构。添加任何新的派生类都需要在该循环中进行修改。如果dou_sth是虚拟函数,我可以用基于范围的for循环调用它。-简单得多。感谢您的回答。@mdjdrn1您已经指出了虚拟函数的所有优点和缺点;如果您在一个地方维护一个派生类列表,当然也可以使用一些宏+模板技巧来生成代码。