簡體   English   中英

C ++需要啟用類成員變量來訪問另一個類的實例的std :: vector

[英]C++ Need to enable class member variables to access an std::vector of instances of another 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類的耦合?

要將自身添加到容器中, 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來避免內存泄漏,盡管這可能會使繼承性變得有點混亂。

這是Ideone的完全WME和第二個選項:

#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;
}

我認為如果實例在創建實例時可以將自己添加到容器中會更好。

這是你的決定,但要三思而后行 - 在大多數情況下,最好保持對象盡可能簡單。 如果您只需要簡化代碼,可以這樣做:

你可以創建外部構造函數 ,類似於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]

現場測試

我絕對建議使用std :: unique_ptr而不是原始指針

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM