为不同类型的参数实现不同的方法
Implementing a different method for different types of arguments
我正在编写一些代码来检测不同形状之间的碰撞,RectShape
、CircShape
、LineShape
都继承自基础 class Shape
。我目前的实施工作非常糟糕。首先,我定义了一堆特定于案例的函数:
bool LineLineCollision(LineShape& line1, LineShape& line2) {
// do some math
}
bool CircRectCollision(CircShape& circ, RectShape& rect) {
// some more math
}
// and so on for all cases
显然所有这些在任何实施中都是必需的。问题出在函数 bool TestCollision(Shape& shp1, Shape& shp2)
中,它接受两个参数,然后通过 many if 语句将 typeid(shp1)
和 typeid(shp2)
与 typeid
我所有派生的 classes。它又脏又乱,但当时我没有任何其他想法。现在我想清理它。添加一种新的形状是难以想象的烦人和耗时。
我现在的新想法是简单地用适合不同参数类型的参数重载 TestCollision
,但是我必须将 TestCollision(CircShape&, RectShape&)
和 TestCollision(RectShape&, CircShape&)
作为两个单独的重载,这就是不可维护。另一个想法是在派生的 classes 本身内部实现函数,但它仍然会导致代码重复并且更难维护。
我该如何解决这个问题?
A 解决方案是使用回调。例如
#include <iostream>
struct Line;
struct Circ;
struct Shape {
virtual void Collision(Line*) = 0;
virtual void Collision(Circ*) = 0;
virtual void Collision(Shape*) = 0;
};
class Line : public Shape {
private:
void Collision(Line*) override {
std::cout << "Line-Line\n";
}
void Collision(Circ*) override {
std::cout << "Circ-Line\n";
}
public:
void Collision(Shape* other) override {
other->Collision(this);
}
};
class Circ : public Shape {
private:
void Collision(Line*) override {
std::cout << "Line-Circ\n";
}
void Collision(Circ*) override {
std::cout << "Circ-Circ\n";
}
public:
void Collision(Shape* other) override {
other->Collision(this);
}
};
#include<memory>
int main(){
std::unique_ptr<Shape> obj1 = std::make_unique<Line>();
std::unique_ptr<Shape> obj2 = std::make_unique<Circ>();
std::unique_ptr<Shape> obj3 = std::make_unique<Line>();
obj1->Collision(obj2.get());
obj1->Collision(obj3.get());
}
输出:
Line-Circ
Line-Line
我正在编写一些代码来检测不同形状之间的碰撞,RectShape
、CircShape
、LineShape
都继承自基础 class Shape
。我目前的实施工作非常糟糕。首先,我定义了一堆特定于案例的函数:
bool LineLineCollision(LineShape& line1, LineShape& line2) {
// do some math
}
bool CircRectCollision(CircShape& circ, RectShape& rect) {
// some more math
}
// and so on for all cases
显然所有这些在任何实施中都是必需的。问题出在函数 bool TestCollision(Shape& shp1, Shape& shp2)
中,它接受两个参数,然后通过 many if 语句将 typeid(shp1)
和 typeid(shp2)
与 typeid
我所有派生的 classes。它又脏又乱,但当时我没有任何其他想法。现在我想清理它。添加一种新的形状是难以想象的烦人和耗时。
我现在的新想法是简单地用适合不同参数类型的参数重载 TestCollision
,但是我必须将 TestCollision(CircShape&, RectShape&)
和 TestCollision(RectShape&, CircShape&)
作为两个单独的重载,这就是不可维护。另一个想法是在派生的 classes 本身内部实现函数,但它仍然会导致代码重复并且更难维护。
我该如何解决这个问题?
A 解决方案是使用回调。例如
#include <iostream>
struct Line;
struct Circ;
struct Shape {
virtual void Collision(Line*) = 0;
virtual void Collision(Circ*) = 0;
virtual void Collision(Shape*) = 0;
};
class Line : public Shape {
private:
void Collision(Line*) override {
std::cout << "Line-Line\n";
}
void Collision(Circ*) override {
std::cout << "Circ-Line\n";
}
public:
void Collision(Shape* other) override {
other->Collision(this);
}
};
class Circ : public Shape {
private:
void Collision(Line*) override {
std::cout << "Line-Circ\n";
}
void Collision(Circ*) override {
std::cout << "Circ-Circ\n";
}
public:
void Collision(Shape* other) override {
other->Collision(this);
}
};
#include<memory>
int main(){
std::unique_ptr<Shape> obj1 = std::make_unique<Line>();
std::unique_ptr<Shape> obj2 = std::make_unique<Circ>();
std::unique_ptr<Shape> obj3 = std::make_unique<Line>();
obj1->Collision(obj2.get());
obj1->Collision(obj3.get());
}
输出:
Line-Circ
Line-Line