指向实例化 classes class 变量的指针?

Pointer to variable of instanced classes class?

我有一个 class 叫做 Shape。 Shape 包含一个名为 geometry 的 Geometry class 实例和一个 vector 类型的指针。 Geometry class 有一个名为 vertices of type vector 的变量。

而不是像这样为我的形状分配顶点:

Shape* myShape = new Shape;
myShape->geometry->vertices = vertices;

我想做:

Shape* myShape = new Shape;
myShape->vertices = &vertices.

为什么?因为它看起来更好看。我可以用一个函数来做到这一点吗?是的,但我不想。为此,在 Shape 的构造函数中,我将其指针设置为几何变量的地址。

Shape::Shape()
{
    geometry = new Geometry; // have also tried Geometry()
    vertices = &(geometry->vertices); // vertices declared as vector<vec3>* vertices in header
}

除非我将顶点分配给 myShape->vertices,否则它们不会分配给 myShape->geometry->vertices。似乎他们仍然被分配给 myShape->vertices。是什么赋予了?如何将指针连接到我的实例 class、classes 成员并切断中间人?

因为 Shape::vertices 是一个指针,所以当您执行

时,您只是将它重新绑定到另一个对象
myShape->vertices = &vertices

你没有像你想的那样将 vertices 复制到 Geometry::vertices 中。

虽然我不同意你的方法(它违反了 open/closed 原则等多项内容),但你可以通过返回对 Geometry::vertices 的引用来实现你想要的。

private:
Geometry geometry;

public:
vector<vec3>& Shape::vertices() { return geometry->vertices;}

并使用:

myShape->vertices() = vertices;

更好的策略:

  1. 避免在构造函数中获取非托管资源。您正在构造函数中获取 Geometry 对象的实例并将其分配给原始指针。这可能会导致问题,例如如果您的构造函数失败,该对象会发生什么?一般来说,观察RAII是一个好习惯。那就是在你的情况下使用智能指针。

在代码中:

Shape::Shape(): geometry(new Geometry()) {}
private:
std::unique_ptr<Geometry> geometry;
  1. 不要公开成员变量: 我认为公开 class 的数据成员从来都不是一个好主意,更不用说指针数据成员了.通过公开数据成员 1) 您需要用户对 class 的了解超越 class 的实现方式。 2) 在不重构所有 class 用户代码的情况下,您将关闭内部实现中未来更改的大门。 3) 你的 class 成员通常是那个 class 的不变性,通过暴露他们,用户可能会破坏事情。

总而言之,我将以这种方式重新设计您的代码:

class Geometry
{
  private:
    std::vector<vec3> vertices;
  public:
    void addVertex(vec3& vtx) { vertcies.push_back(vtx);}
    void addVertices(std::vector<vec3>& vtxs) { for(auto& vtx:vtxs){ vertices.push_back(vtx);}}
}

class Shape
{
  private:
    std::unique_ptr<Geometry> geometry;

  public:
    Shape(): geometry(new Geometry()) {}
    void addVertex(vec3& vtx) { geometry->addVertex(vtx);}
    void addVertices(std::vector<vec3>& vtx) { geometry->addVertices(vtxs);}
}

P.S。我假设你的 Geometry::vertices 是你问题中暗示的 vector<vec3> 类型..

恶解

如果您不介意在 Shape 对象上花费 sizeof(void*) 额外字节,您可以将包装器 class(和包装器对象)添加到您的 Shape class:

class ShapeVerticies{
public:
    ShapeVerticies(Shape* shape)
        : shape(shape){
    }

    void operator=(const std::vector<vec3>& a){
        shape->geometry->verticies = a;
    }

    Shape* shape;
};
ShapeVerticies verticies;

当然,您应该在 Shape 构造函数中使用 this 初始化 verticies

邪恶的解决方案

并且您可以将此 space 要求减少到单个字节(可能是单个字节,这是编译器的选择)。无论如何,我警告你不要那样做。

class ShapeVerticiesEvil{
public:
    void operator=(const std::vector<vec3>& a){
        Shape* thisShape = reinterpret_cast<Shape*>(reinterpret_cast<unsigned char*>(this) - offsetof(Shape, verticies));
        thisShape->geometry->verticies = a;
    }
};
ShapeVerticiesEvil verticiesEvil;