多态性的良好实践
Good practice of polymorphism
本文关键字:多态性 更新时间:2023-10-16
假设Domain
存储指向Shape
的指针。确切的形状(Triangle
或Rectangle
)在编译时不知道,在读取输入后就会清楚了。在运行时,我可能需要访问派生结构的变量,但这是不可能的,因为指针指向基结构。我找到了另一种解决方案,那就是"开关式",但正如这里的答案所指出的那样,这是不鼓励的。他还说
当你使用多态性时,你不需要关心基类引用/指针背后的内容。
在这种情况下,我确实关心,所以听起来我不应该使用多态性。我想我下面所做的是一个糟糕的设计,那么解决这个问题的好设计是什么呢?
struct Shape
{
int common_variable;
};
struct Triangle: Shape
{
int triangle_specific_variable;
};
struct Rectangle: Shape
{
int rectangle_specific_variable;
};
struct Domain
{
Shape* shape;
};
int main()
{
Domain domain;
//domain.shape = new Triangle(); // depends on input.
//domain.shape = new Rectangle(); // depends on input.
return 0;
}
你的问题清楚地显示了多态性的需要,因为你想要与三角形,长方形等工作,你知道所有这些都是形状。
为什么不建议通过交换机访问特定的数据
因为这与多态设计完全相反。而不是处理形状,绘制它们,计算它们的面积等等……您总是需要知道形状的类型和特定于代码的行为。
想象一下,你已经完成了你的代码,然后你发现你还想要正方形和圆形:维护这将是一个多么可怕的噩梦。
如何解决这个问题
你必须从具体的类中抽象出来,并定义可以在一般形状上执行的一般操作。然后将这些操作定义为虚函数,在使用Domain的代码中,只需调用虚函数即可。
进一步推广,而不是从类中创建对象,你可以使用一个工厂方法,例如从流返回一个形状。
例子:
class Shape
{
public:
virtual void scale(double scale_factor)=0;
virtual void rotate(double angle)=0;
virtual void draw(window w)=0;
virtual Shape* clone()=0;
virtual ~Shape() {}
};
class Triangle: public Shape
{
Point A, B, C;
public:
Triangle (Point a,Point b, Point c) : A(a), B(b), C(c) { }
void scale(double scale_factor) override;
void rotate(double angle) override;
void draw(window w) override;
Shape* clone() { return new Triangle(*this); }
};
...
int main()
{
Domain domain, domain2;
Window wnd = CreateWindow(...); // depends on your GUI library
Point a,b,c;
cin >> a >> b >> c;
domain.shape = new Triangle(a,b,c);
// Once the object is constructed no need to know the details of the shape here
domain.shape->rotate(45);
domain2.shape = domain.shape->clone();
domain.shape->draw(wnd);
...
return 0;
}
请注意,使用智能指针比使用原始指针更安全;
第一。当具体对象具有完全相同的接口时,多态几乎总是最合适的工具。
第二,这种情况很少,有时多态性比变体更合适。
在这种情况下,我们将行为推迟到实现中,而不是试图从对象外部推断它。一种方法是使用"访问者模式":
struct triangly_thing { int i; };
struct rectangly_thing { int i; };
struct shape_visitor
{
virtual void operator()(triangly_thing thing) const
{
// do triangly things
}
virtual void operator()(rectangly_thing thing) const
{
// do rectangly things
}
};
struct Shape
{
int common_variable;
virtual void visit(shape_visitor const& visitor)
{
}
};
struct Triangle: Shape
{
triangly_thing my_triangly_thing;
void visit(shape_visitor const& visitor) override
{
visitor(my_triangly_thing);
}
};
struct Rectangle: Shape
{
rectangly_thing my_rectangly_thing;
void visit(shape_visitor const& visitor) override
{
visitor(my_rectangly_thing);
}
};
struct Domain
{
Shape* shape;
};
int main()
{
Domain domain;
struct my_shape_visitor_type : shape_visitor
{
// customise overrides in here
} my_shape_visitor;
domain.shape->visit(my_shape_visitor);
return 0;
}
相关文章:
- 多态性和功能结合
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- C++boost序列化多态性问题
- 如何查找哪个类对象位于数组的特定索引上(多态性)
- 如何在多线程中正确使用unique_ptr进行多态性?
- 具有智能指针的多态性
- 在 C++ 中在堆栈上创建实例时如何保持多态性?
- 继承/多态性 - 我是否被迫使用"protected"变量?
- C++ 多态性在代码::块 17.12 中不起作用
- C++ 泛型和多态性:这种模式可行吗?
- 为什么我们实际上需要运行时多态性?
- 如何在这个简单的最小示例中实现多态性?
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 无法初始化已知大小的矢量指针,该大小不会因多态性而更改
- 运行时多态性和dynamic_cast需要澄清
- 如何调用指针类型的方法(禁用多态性)?
- 从基类调用函数的多态性
- 运行时多态性 - 箭头运算符访问了错误的成员?
- 为什么我在虚幻引擎中的多态性和接口方面遇到问题?