为 3D 数组定义 setter/getter 个属性

Define setter/getter attributes for a 3D array

在 C++ 中,我有一个 class,其中包含一个已定义类型的 3d 数组。我需要定义几个值为 int 的属性,并且能够设置和获取 3d 数组的属性。

    //header;
    class Voxel
    {
      private:
        vector< vector < vector < myPoints* > > > Vox; // 3D array
      public:
        //... 
     };

     //Here is the constructor and methods of the class:
     Voxel::Voxel(myType var1; double var2)
     {
     // this is constructor

     } 

例如,我需要像这样定义具有 int 值的 "Attributes":

Attributes:
LabelTag; // Vox tag e.g. an int tag=2
NumberofPoints; // Vox nr of containing points e.g. int nr=5


Vox.setAttribute(LabelTag tag, Value 2);
Vox.setAttribute(NumberofPoints nr, Value 5);

int tag        = Vox.getAttribute(LabelTag);
int nrofpoints = Vox.getAttribute(NumberofPoints);

我应该如何定义属性,如 struct 或 typedef 或其他东西,然后如何将值设置为我的 3D 数组成员,例如沃克斯, 我想给 Vox 本身设置属性,而不是里面的点?可能吗? 它们应该定义为私有还是 public?

编辑: 看到 George Purcell 的回答,我可能误解了你的问题,以为是关于从体素外部访问点 class...

虽然我没有删除答案,但我仍然把它留在这里,以防你 运行 在 以后 遇到这个问题并发现它有用 然后...


除了 StoryTeller 已经指出的指针问题,您还有一个小问题:

您可以简单地定义一个索引运算符,但此索引运算符随后将被迫 return 对 vector<vector<myPoints*>>(少一个向量)或 vector<vector<vector<myPoints*>>>::iterator 的引用。

但是,这将允许用户修改基础向量,例如。 G。清除它们。如果您现在 returned const vector 或 const_iterator,用户将无法修改存储的值(调用 setAttribute...)。此外,他可以放弃 const,至少在第一种情况下,然后再次做他想做的事...

所以你有两个选择:

  1. 你写了一个明确的getter函数:
    mypoints* getPoints(int x, int y, int z) { return vox[x][y][z]; }
  2. 您将向量包装成单独的 classes。然后每个 class 都可以提供对其底层向量的适当访问,同时防止用户做非法的事情。然后,每个 classes 都会提供自己的运算符 [],就像你的外部 Voxel class:
  3. 一样

class Voxel
{
public:
    class Points1D
    {
        vector<myPoints*> points;
    public:
        myPoints* operator[](unsigned int index) { return points[index]; }
    };
    class Points2D
    {
        vector<Points1D> points;
    public:
        Points1D& operator[](unsigned int index) { return points[index]; }
    };
    Points2D& operator[](unsigned int index) { return points[index]; }
private:
    vector<Points2D> points;
};

如果你希望能够迭代你的 classes,那么你也必须提供适当的迭代器,并且可能还需要提供其他东西(例如 size() 函数)——这取决于什么用户应该能够使用您的 classes...

在第二个代码块下方编辑了答案。

好的,首先正如@StoryTeller 所评论的那样,您的向量正在存储指针;所以你需要使用 -> 语法来访问它们指向的 object 。

因此,您可能应该设置一个 myPoints class,因为结构并不常见(C++ 中的结构与 class 相同,只是它们的属性和函数的默认访问修饰符是 public).我想象这个 class 看起来像

class myPoints // you should probably split this into a header and cpp
{
    int tag;
    int noOfPoints;

    myPoints() : tag(0), noOfPoints(0) // construct with whatever values, you can pass your own
    {}

    void setNoOfPoints(noOfPoints)
    {
        this->noOfPoints = noOfPoints;
    }

    void setTag(tag)
    {
        this->tag = tag;
    }

    int getNoOfPoints(){ return noOfPoints; }
    int getTag(){ return tag; }
};

假设您已经使用一些 *myPoints 文字初始化了 vox,然后您可以按如下方式简单地访问和使用您的 myPoints objects

int tag = Vox.at(i).at(j).at(k)->getTag();
int noOfPoints = Vox.at(i).at(j).at(k)->getNoOfPoints();

Vox.at(i).at(j).at(k)->setNoOfPoints(6);
Vox.at(i).at(j).at(k)->setTag(6);

留下上面的答案,就像@Aconcagua 的答案一样,您将来可能会发现它有用。

无论如何,我想我对你想要做的事情理解得更好一些,考虑到你已经按照@StoryTeller 所说编写的代码,你可以只使用你的 Voxel class 来保存标签和每个向量的 noOfPoints 属性。体素 class 看起来像(原谅我没有提供 header 的懒惰)

class Voxel
{
private:
    vector< vector < vector < myPoints* > > > Vox; 

    int tag;
    int noOfPoints;
public:
    Voxel() : tag(0), noOfPoints(0) // construct with whatever values, you can pass your own
    {}

    vector< vector < vector < myPoints* > > >& getVox(){ return Vox; } //Ignore my shitty naming scheme, you can use this to set or get elements

    void setNoOfPoints(noOfPoints)
    {
        this->noOfPoints = noOfPoints;
    }

    void setTag(tag)
    {
        this->tag = tag;
    }

    int getNoOfPoints(){ return noOfPoints; }
    int getTag(){ return tag; } 
};

然后访问你的矢量并设置你的标签和 noOfPoints,只需创建一个 Voxel 实例,它应该看起来像这样

//A new vector of voxels

vector<Voxel> voxels;

voxels.push_back(Voxel); // this only needs to be a 1d array, you can construct each voxel however you like and add as many as you like

//settting the tag for the first element

voxels[0].setTag(0);

//getting the tag for the first element 

int tag = voxels[0].getTag();

// manipulating the contained vector 

voxels[0].getVox().at(i).at(j).at(k) = //whatever you are storing in your vector

也许这不是你问题的答案,但看起来你来自 C#-kind 世界,所以你让我澄清一些事情(我希望你能够重新表述你的问题,以便普通c++程序员都能看懂:)

属性的概念和C++完全不一样meaning(我觉得跟你要实现的东西无关)

C++ 中也没有单独的属性概念(又名 getters/setters)。 相反,您只需编写 getSmth() 或 setSmth(type arg) 成员函数。 它们的目的只是为用户提供对私有成员变量的受控访问。然而,这些函数只是具有特殊能力的常规成员函数。

如果你想get/set一个成员变量说"tag"从class说"myPoint"你需要定义一个成员函数

class myPoint
{
 private:
    int tag;
//...
 public:
    int GetTag();
    {
       return tag; // return this->tag;
    }

    void SetTag(int t)
    {
       tag = t;
    }
}

那你可以写

int main()
{
   vector<vector<vector<myPoint*>>> Vox;
   Vox[1][2][3]->SetTag(10);
   cout << Vox[1][2][3]->GetTag();
}

但是假设您有几个 getters/setter 用于不同的变量。 那就没办法写

Vox[1][2][3]->GetAtribute(tag);

并期望编译器找出 "oh, he needs to get a value of tag member variable"。 在 C++ class 系统中,只有 class 成员变量和可以使用它们的成员函数——一切就这么简单:)

有趣的是,您不仅可以使用值参数化任何函数,还可以使用类型参数化任何函数。然后,您将能够创建一个函数模板,并根据您设置的类型调用同一函数的不同版本。您可以使用它来定义要调用 getter 或 setter.

的属性(实际上是成员变量)
// LableTag is a class defined globally and GetAttribute() is a member
//template function
int i = Vox[1][2][3]->GetAttribute<LableTag>(); 

但是,我还没有看到它被用于定义 getters/setters。通常如果你想 "get something" 你只需要写一个具体的成员函数 GetSomething();