C ++需要启用类成员变量来访问另一个类

时间:2016-10-18 08:53:13

标签: c++ class

我正在开发一个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,就像其他类似的类SegmentTriangle一样。我需要这个能够将不同的形状添加到单个容器中,以便稍后在一个地方方便地处理它们。

main函数中,我声明容器,然后创建Point的实例,然后push_back到容器:

std::vector<AbstractShape*> shapes;
Point* p1 = new Point(100, 50);
p1->setLabel("A", 4);
shapes.push_back(p1);

我认为如果实例在创建实例时可以将自己添加到容器中会更好。为此,Point类应该能够从内部查看容器。实现这一目标的最佳方法是什么,而不是引入过多的Point类耦合?

2 个答案:

答案 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_ptrunique_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_sharestd::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]

Live test

我绝对建议使用std::unique_ptr而不是原始指针