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
函数之间分布时,此代码看起来会更好。希望我正确理解您的意思。