指向实例化 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;
更好的策略:
- 避免在构造函数中获取非托管资源。您正在构造函数中获取
Geometry
对象的实例并将其分配给原始指针。这可能会导致问题,例如如果您的构造函数失败,该对象会发生什么?一般来说,观察RAII是一个好习惯。那就是在你的情况下使用智能指针。
在代码中:
Shape::Shape(): geometry(new Geometry()) {}
private:
std::unique_ptr<Geometry> geometry;
- 不要公开成员变量: 我认为公开 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;
我有一个 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;
更好的策略:
- 避免在构造函数中获取非托管资源。您正在构造函数中获取
Geometry
对象的实例并将其分配给原始指针。这可能会导致问题,例如如果您的构造函数失败,该对象会发生什么?一般来说,观察RAII是一个好习惯。那就是在你的情况下使用智能指针。
在代码中:
Shape::Shape(): geometry(new Geometry()) {}
private:
std::unique_ptr<Geometry> geometry;
- 不要公开成员变量: 我认为公开 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;