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

Define setter/getter attributes for a 3D array

本文关键字:getter 属性 setter 定义 3D 数组      更新时间:2023-10-16

在c++中,我有一个包含定义类型的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);

我应该如何定义属性,作为结构体或作为类型定义或其他东西,然后我如何设置我的3D数组成员的值,例如Vox,我想设置Vox本身的属性,而不是里面的点?这可能吗?它们应该被定义为私人的还是公共的?

在第二段代码下面编辑答案

好的,首先正如@StoryTeller所评论的,你的矢量存储指针;因此,您需要使用->语法来访问它们所指向的对象。

所以你可能应该设置一个myPoints类,因为结构体不常见(c++中的结构体与类是一样的,除了它们的属性和函数的默认访问修饰符是public)。我想象这个类看起来像

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对象,如下所示

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类来保存每个向量的标签和noOfPoints属性。Voxel类看起来像(原谅我的懒惰,没有提供标题)

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,简单地创建一个实例的体素,它应该看起来像这样

//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

编辑:看到George Purcell的回答,我可能误解了你的问题,认为这是关于从外部访问Voxel类的点…

没有删除答案,但是,我仍然把它留在这里,以防您以后遇到这个问题并发现它很有用然后


除了StoryTeller已经提到的指针问题,你还有一个小问题:

您可以简单地定义一个索引操作符,但是这个索引操作符将被迫返回对vector<vector<myPoints*>>(少一个向量)或vector<vector<vector<myPoints*>>>::iterator的引用。

然而,这将允许用户修改底层向量,例如清除它们。如果现在返回const vector或const_iterator,用户将无法修改存储的值(调用setAttribute…)。此外,他可以抛弃const,至少在第一种情况下,然后再做他想做的事情…

你有两个选择:

    你写一个显式的getter函数:
    mypoints* getPoints(int x, int y, int z) { return vox[x][y][z]; }
  1. 将向量包装到单独的类中。然后,每个类都可以提供对其底层向量的适当访问,同时防止用户进行非法操作。每个类都会提供自己的操作符[],就像你的外部体素类一样:

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

如果你希望能够迭代你的类,那么你也必须提供适当的迭代器,也可能提供其他东西(例如size()函数)——这取决于用户将能够对你的类做什么。

也许这不是你的问题的答案,但它看起来像你来自c#的世界,所以你让我澄清一些事情(我希望然后你将能够重新制定你的问题,以便普通的c++程序员可以理解:)

属性的概念在c++中有完全不同的含义(我认为与你想要实现的无关)

在c++中也没有单独的属性概念(也就是getter/setter)。相反,您只需编写getSmth()或setSmth(type arg)成员函数。它们的目的只是为用户提供对私有成员变量的受控访问。然而,这些函数只是普通的成员函数,现在具有特殊的功能。

如果你想从类中获取/设置一个成员变量比如"tag"比如"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();
}

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

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

并期望编译器找出"哦,他需要获得标记成员变量的值"。在c++类系统中,只有类成员变量和成员函数可以使用它们——就这么简单:)

有趣的是,你不仅可以用值参数化任何函数,还可以用类型参数化函数。然后,您将能够创建一个函数模板,并根据所设置的类型调用同一函数的不同版本。您可以使用它来定义要为哪个属性(实际上是成员变量)调用getter或setter。

// LableTag is a class defined globally and GetAttribute() is a member
//template function
int i = Vox[1][2][3]->GetAttribute<LableTag>(); 

然而,我还没有看到它被用于定义getter/setter。通常,如果你想"获取某些东西",你只需编写一个具体的成员函数GetSomething();