我正在开发一个API,它可以让你绘制简单的几何形状并计算它们的元素。该项目基于SFML库。
我有这堂课:
#ifndef POINT_H_INCLUDED
#define POINT_H_INCLUDED
#include "stdafx.h"
#include "Helper.h"
class Point : public AbstractShape
{
public:
Point(float x, float y);
Vector getCoords();
sf::VertexArray getShape();
void setLabel(std::string label, int param);
private:
float m_x, m_y, m_R;
std::string m_label;
sf::VertexArray m_shape;
sf::Text m_labelObject;
};
#endif
它继承自抽象类AbstractShape
,就像其他类似的类Segment
和Triangle
一样。我需要这个能够将不同的形状添加到单个容器中,以便稍后在一个地方方便地处理它们。
在main
函数中,我声明容器,然后创建Point
的实例,然后push_back
到容器:
std::vector<AbstractShape*> shapes;
Point* p1 = new Point(100, 50);
p1->setLabel("A", 4);
shapes.push_back(p1);
我认为如果实例在创建实例时可以将自己添加到容器中会更好。为此,Point
类应该能够从内部查看容器。实现这一目标的最佳方法是什么,而不是引入过多的Point
类耦合?
答案 0 :(得分:4)
要将自身添加到容器中,Point
需要与容器耦合。将两者结合起来似乎是一个坏主意:为什么Point
应该对std::vector
有所了解?
如果您经常在代码中使用此模式,最好定义一个函数来实例化并将该点添加到容器中:
template<typename T=std::vector<Point*>>
Point *makePoint(int x, int y, T container) {
Point *p = new Point(x, y);
container.push_back(p);
return p; // so we can set other properties easily
}
或者创建另一个Context
类,它封装了一组点:
template <typename T=std::vector<Point*>>
class Context {
T container;
public:
Point* addPoint(int x, int y) {
Point *p = new Point(x, y);
container.push_back(p);
return p;
}
};
此外,您可能希望使用shared_ptr
或unique_ptr
来避免内存泄漏,尽管这可能会因为继承而变得有点混乱。
Here's a fully WME on Ideone第二个选项:
#include <iostream>
#include <vector>
using namespace std;
class Point {
public:
Point (int x, int y) {}
};
template <typename T=std::vector<Point*>>
class Context {
T container;
public:
Point* addPoint(int x, int y) {
Point *p = new Point(x, y);
container.push_back(p);
return p;
}
};
int main() {
Context<> c;
c.addPoint(1, 2);
return 0;
}
答案 1 :(得分:0)
我认为如果实例可以添加自己更好 创建实例时的容器。
这是你的决定,但要三思而后行 - 在大多数情况下,最好保持对象尽可能简单。如果您只需简化代码,可以这样做:
您可以设置外部构建功能,类似于std::make_share和std::make_tuple:
这将使您能够致电:
construct<Point>(container, 1, 2);
construct<Line>(container, 1, 2, 3, 4);
它将构建Point / Line并在一行中放入容器
完整代码:
#include <iostream>
#include <vector>
using namespace std;
struct AbstractShape
{
virtual std::ostream& dump(std::ostream&) = 0;
};
struct Point : AbstractShape
{
Point(float x, float y) : x(x), y(y) {}
virtual std::ostream& dump(std::ostream& o) override
{
return o << "P[" << x << ":" << y << "]";
}
float x, y;
};
struct Line : AbstractShape
{
Line(float x1, float y1, float x2, float y2) : x1(x1), y1(y1), x2(x2), y2(y2) {}
virtual std::ostream& dump(std::ostream& o) override
{
return o << "L[" << x1 << ":" << y1 << "," << x2 << ":" << y2<< "]";
}
float x1, y1, x2, y2;
};
template<typename Object, typename Container, typename ...Args>
Object* construct(Container& c, Args... args)
{
Object* res = new Object(args...);
c.push_back(res);
return res;
}
int main() {
std::vector<AbstractShape*> container;
construct<Point>(container, 1, 2);
construct<Line>(container, 1, 2, 3, 4);
for (auto s : container)
s->dump(std::cout) << std::endl;
return 0;
}
输出:
P[1:2]
L[1:2,3:4]
我绝对建议使用std::unique_ptr而不是原始指针