【问题标题】:Initializing a variable in the constructor?在构造函数中初始化变量?
【发布时间】:2020-09-27 15:09:10
【问题描述】:

我正在尝试使用向量作为成员字段来设置对象。我设置了构造函数,据我所知,它确实初始化了这个成员变量,但是当我尝试访问向量时出现错误,除非我在对象的函数调用中初始化它。我收到警告说

C26495: Variable 'Engy::Graphics::Shape2D::m_vertices' is uninitialized. Always initialize a member variable (type.6).

问题是,我确实在构造函数中初始化了它。我缺少什么重要的东西吗?这是我的代码:

类声明(头文件)

class Shape2D:Object
        {
            protected:
                std::vector<Vector> *m_vertices;
                int type = GL_QUADS;
            public:
                Shape2D(std::vector<Vector> vertices);
                Shape2D();
                void draw();
                void setVector(int index, Vector value);
                Vector getVector(int index);
                void translate(double x, double y);
                void createVector(int i, double x, double y);
                void createVector(double x, double y);
                void addVector(Vector value);
        };

方法声明(.cpp 文件)

Shape2D::Shape2D(std::vector<Vector> vertices)
{
    std::vector<Vector> m_vertices = vertices;
}
Shape2D::Shape2D()
{
    std::vector<Vector> *m_vertices = new std::vector<Vector>;
}

void Shape2D::setVector(int index, Vector value)
{
    //THIS PART RIGHT HERE IS WHAT I HAVE TO DO TO MAKE IT NOT CRASH, BUT I DONT WANT TO HAVE TO PUT THIS EVERYWHERE
    if (!m_vertices)
    {
        m_vertices = new std::vector<Vector>;
    }
    if (m_vertices->size() < index)
    {
        m_vertices->assign(index - m_vertices->size(), NULL);       
    }
    m_vertices->at(index) = value;
}

对象创建

    //Rectangle is a subclass of Shape2D which calls the default constructor of Shape2D then runs calls to add the constructor inputs in (Let me know if you would like to see that code)
    Rectangle r(0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.0, 0.5);

谢谢你们!

【问题讨论】:

  • 为什么成员变量m_vertices是指针?为什么不只是一个std::vector
  • 很抱歉,但请仔细阅读您的书/教程/课程作业,或者如果他们没有清楚地解释如何初始化成员,请获得更好的。
  • 是的,我是自学 c++,我来自 java 和 c#,所以这对我来说是全新的哈哈
  • @LincolnDoney:对于从 Java 学习 C++,这里有一个提示:不要使用new,并且几乎不要使用T* 指针。

标签: c++ inheritance vector std glfw


【解决方案1】:
  1. 您在构造函数中定义和初始化一个名为 m_vertices 的局部变量,而不是类的成员变量。
  2. 您不应使用指针、newdelete - 成员向量归类实例“所有”。

... 和其他答案建议基于这些更正的课程设计(例如@RSahu 的答案)。然而——还是有问题。对我来说,您希望一方面能够对形状的顶点进行完全编辑控制,另一方面保持顶点矢量受到保护,这对我来说是没有意义的。此外,预计形状不会增长、增长和增长。所以我会建议完全不同的东西:

class Shape2D : Object {
public:
    using vertex_type = Vector;
    using vertices_type = std::vector<vertex_type>;
protected:
    const vertices_type m_vertices;
public:
    Shape2D() = delete;
    Shape2D(vertices_type vertices) : m_vertices(std::move(vertices)) { }
    Shape2D(const Shape2D& shape) = default;
    Shape2D(Shape2D&& shape) = default;

    // other methods here, but -  no methods for editing vertices!
}

现在,就其顶点而言,形状(本质上)是不可变的。想改变形状?创建一个新的形状对象。

或者,如果您必须拥有对顶点的编辑权限(我对此表示怀疑) - 考虑通过访问器方法公开m_vertices,或者在Shape2D 或在子类中,比如@ 987654327@:

vertices_type& EditableShape2D::vertices() { return m_vertices; }

并不是你遇到的所有麻烦。

【讨论】:

  • 有趣的 POV。 Shape 是否不可变是一种设计选择。在大多数情况下,您希望能够就地编辑对象而不是构建新对象。
  • @RSahu:添加了关于不需要添加所有这些添加/删除/更改方法的建议。
  • 这可能是最聪明的举动.. 我会调查的。谢谢!
  • 仍然保留 draw() 方法和其他使用向量但不改变它们的方法是一个好的举措吗?
  • @LincolnDoney:哦,当然,我不是说删除所有方法,请参阅编辑。
【解决方案2】:

线

std::vector<Vector> m_vertices = vertices;

不初始化成员变量。它初始化一个同名的函数局部变量。函数局部变量隐藏/隐藏成员变量。

最佳做法是使用member-initialization-list 语法初始化成员。

Shape2D::Shape2D(std::vector<Vector> vertices) : m_vertices(vertices)
{
}

这将需要对您的班级进行一次更改。您需要将m_vertices 更改为矢量对象而不是指针。

std::vector<Vector> m_vertices;

无论如何,这是一个很好的做法。

【讨论】:

  • 我建议 OP 走得更远。
【解决方案3】:

在这个构造函数中:

Shape2D::Shape2D()
{
    std::vector<Vector> *m_vertices = new std::vector<Vector>;
}

你声明了一个单独的变量m_vertices,所以成员变量永远不会被初始化。

相反,您应该这样做:

Shape2D::Shape2D()
{
   m_vertices = new std::vector<Vector>;
}

但是,您应该使用成员初始化器列表来初始化成员,如下所示:

Shape2D::Shape2D() : m_vertices {new std::vector<Vector>} {}

请注意,您的单个构造函数参数也需要修复。这将导致错误,因为类型不匹配。您也可以通过在那里分配内存来解决此问题。

话虽如此,我建议重新考虑设计,看看是否可以完全避免手动内存管理。例如你还没有定义析构函数,所以你会泄漏内存。此外,您需要自己实现复制构造函数等。

【讨论】:

  • 成员初始化应尽可能在初始化列表中执行,而不是在构造函数主体中。所以,@RSahu 的建议是更好的建议。
【解决方案4】:

在默认构造函数中:

Shape2D::Shape2D()
{
    std::vector<Vector> *m_vertices = new std::vector<Vector>;
}

您定义了一个名为m_vertices 的全新变量,该变量与具有相同名称的Shape2D 成员变量不同且独立。这个局部变量shadow是成员变量。

您可以使用成员初始化器列表来解决该问题:

Shape2D::Shape2D()
    : m_vertices{ new std::vector<Vector> }
{
}

你在另一个构造函数中也有类似的问题,但也有不同的问题:参数不是指针,你不能让m_vertices指向那个参数。对此的解决方案是根本不为向量使用指针。您几乎不需要指向容器的指针。

所以实际上两个问题的解决方案只是将类中的m_vertices声明为普通对象,而不是指针:

class Shape2D
{
    std::vector<Vector> m_vertices;  // Not a pointer
    ...
};

【讨论】:

    猜你喜欢
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多