C++ 是否建议使用动态强制转换为派生类虚拟函数提供输入?

C++ 是否建议使用动态强制转换为派生类虚拟函数提供输入?,c++,virtual-functions,dynamic-cast,C++,Virtual Functions,Dynamic Cast,我在书中读了一些答案 最符合我的情况的是 #include<iostream> class Shape { public: virtual void draw()=0; virtual ~Shape(){}; }; class Rectangle : public Shape { public: int length; int breath; void draw() { st

我在书中读了一些答案

最符合我的情况的是

#include<iostream>

class Shape
{
   public:
      virtual void draw()=0;
      virtual ~Shape(){};
};

class  Rectangle : public Shape
{
   public:
      int length;
      int breath;

      void draw()
      {
         std::cout<<"RECTANGE"<<std::endl;
      }

};


class  Circle : public Shape
{
   public:
      int diameter;

      void draw()
      {
         std::cout<<"CIRCLE"<<std::endl;
      }

};


/*Abstract Factory*/

Shape* getShapeObj(int type)
{
   switch(type)
   {
      case 1:
         return new Rectangle;

      case 2:
         return new Circle;

         /*  many types will be added here in future. */
   }

   return NULL;
};

void drawShapes(Shape *p_shape[],int len)
{
   for(int i=0;i<len;i++)
      p_shape[i]->draw();
}

int main()
{
   Shape *l_shape[2];
   l_shape[0]=getShapeObj(1);
   l_shape[1]=getShapeObj(2);
   Rectangle *l_rec=dynamic_cast<Rectangle*>(l_shape[0]);

   if(l_rec)
   {
      l_rec->length=10;
      l_rec->breath=20;
   }

   Circle *l_circle=dynamic_cast<Circle*>(l_shape[1]);

   if(l_circle)
      l_circle->diameter=25;

   drawShapes(l_shape,2);

}
#包括
阶级形态
{
公众:
虚空绘制()=0;
虚拟~Shape(){};
};
类矩形:公共形状
{
公众:
整数长度;
内呼吸;
作废提款()
{

解决方案是在c++11中引入的函数参数的完美转发

template<typename ...CtorArgs>
Shape* getShapeObj(int type, CtorArgs&& ctor_args...)
{
   switch(type)
   {
      case 1:
         return new Rectangle(std::forward<CtorArgs>(ctor_args)...);
     // many types will be added here in future.
   }

    return NULL;
}
模板
Shape*getShapeObj(int类型、CtorArgs和&CtorArgs…)
{
开关(类型)
{
案例1:
返回新矩形(std::forward(ctor_args)…);
//未来将在此处添加许多类型。
}
返回NULL;
}
显然,将函数设置为模板会破坏隐藏层次结构的目的(以及对构造函数的参数数量提出相当严格的要求)。但是,如果基包含进行构造的函数的映射,并且每个派生类使用指向构造它的函数的指针更新该映射,则仍然可以隐藏信息



我最近写了一篇关于在映射中存储类型擦除的函数指针的文章,其中一些静态类型检查被转发到运行时。

在这种特殊情况下,看起来您的
main
函数承担了太多的责任。如果您有
圆圈
六边形
MyFancyFigure
类型呢它们应该在不同分支的
main
中初始化

最好将“初始化”逻辑移到类中的一个单独的虚拟函数
init
(甚至移到构造函数中)。代码如下所示:

class Shape
{
   public:
      virtual void draw()=0;
      virtual void init()=0;
      virtual ~Shape(){};
};

class  Rectangle : public Shape
{
   public:
      int length;
      int breath;

      void draw()
      {
         //Draw Rectangle
      }

      void init()
      {
         length = 10;
         breath = 20;
      }
};

int main()
{
   Shape *l_shape=getShapeObj(1);
   // Calls different code of "init" method depending on the actual object type
   l_shape->init();
   l_shape->draw();
   delete l_shape;
}

此外,请注意,此初始化逻辑可能位于其他位置,如类的构造函数或工厂方法。但
main
肯定是错误的位置。

“传递虚拟函数的输入和输入将因类型而异”-我看不到你的代码中有一个地方使用带有一些输入的虚拟函数…你能详细说明一下吗?你不能重写虚拟函数并更改其参数…上面的代码实现了什么,而
Rectangle*l_rec=new Rectangle(10,20);
没有实现?(或者更好的
auto l_rec=std::make_unique(10,20);
)。我知道这是一个简化的示例,但我看不出这个复杂的示例会是什么样子。@Holt用详细的代码更新了代码example@VinothKumar谢谢。这个
getShapeObj
函数的真正目的是什么?为什么你不能简单地做一些事情,例如
l_形状[0]=新矩形(10,2);
(创建了相应的构造函数后)?这只有在所有子类都有相同的构造函数参数时才有效,因为整个函数体需要良好的格式。@Holt-是的。将其分开以适应不同的构造函数参数需要一定程度的间接性,比如通过标记分派。但关键是有办法避免
动态转换
@alexykuzmin My input将因类型而异。意思是说您已经在init中硬编码了输入。@VinothKumar如果它取决于类型,您现在可能在
main
函数中有多个If。当在派生类的多个
init
函数之间分布时,此代码看起来会更好。希望我正确理解您的意思。