【问题标题】:C++ can't modify private variable with setter in a class of classC ++不能在一个类中用setter修改私有变量
【发布时间】:2023-03-05 19:36:01
【问题描述】:

我知道 setter 函数在 C++ 中是基本的,但我似乎无法正确创建一个。

我有一个类Graph,其中包含另一个类Vertex。 在main 中,我实例化了一个Graph 类型的对象,并使用该对象来读取一个将Vertex 类型的对象添加到Graph 的文件。

问题是,之后当我尝试打印出我的Graph 对象时,一切似乎都是空的。我认为我在滥用指针或引用。

你能解释一下为什么我有 6 个 Vertex 对象,但它们都是空的吗? (我试图将Vertexvector 更改为vector* 但这并没有解决我的问题,我想我还是丢失了Vertex 对象......)?

Main.cpp

int main(int argc, char *argv[]){
    Graph g = Graph();
    g.readDotFile("graph.dot");
    std::cout << g << std::endl;
    return 0;
}

Graph.hpp

class Graph{

private:
    class Vertex{

    public:
        Vertex();
        Vertex(std::string name);
        Vertex(Vertex const& v);
        ~Vertex();
        const std::string& getIdVertex()const;
        friend std::ostream& operator<<(std::ostream &os, Vertex const& v);
        void printVertex(std::ostream &os)const;
        void setStartToStart(const std::string& name);

    private:
        std::string idVertex;
        std::vector<std::string> startToStart;

    };

public:
    Graph();
    void readDotFile(std::string dotFile); // Graph from a dot file
    Graph(Graph const& g);
    ~Graph();
    void addVertex(Vertex& v);
    void addEdge(int typeOfEdge, std::string name1, std::string name2);
    const std::vector<Graph::Vertex>& getVertices()const;

    friend std::ostream& operator<<(std::ostream &os, Graph const& g);
    friend std::ostream& operator<<(std::ostream &os, Vertex const& v);
    void printGraph(std::ostream &os)const;
private:
    std::vector<Vertex> vertices;
};

Graph.cpp

#include "graph.hpp"  

Graph::Vertex::Vertex(){}
Graph::Vertex::Vertex(std::string name){
    idVertex = name;

}
Graph::Vertex::Vertex(Graph::Vertex const& v){}
Graph::Vertex::~Vertex(){}

const std::string& Graph::Vertex::getIdVertex()const{ return idVertex; }


void Graph::Vertex::setStartToStart(const std::string& v){
    startToStart.push_back(v);
}
Graph::Graph(){} 
Graph::Graph(Graph const& g){}   
Graph::~Graph(){}
const std::vector<Graph::Vertex>& Graph::getVertices()const{ return vertices; }

void Graph::readDotFile(std::string file){
    std::ifstream dotFileIn(file.c_str());

    std::string line;
    while (getline(dotFileIn, line)){
            // Read the file, the problem don't come from here, I just don't show the code
        addEdge(1, "origin", "destination");
        }
    }
}

void Graph::addVertex(Graph::Vertex& v){ // Before create, verify the vertex does not exist
    vertices.push_back(v);    
}

void Graph::addEdge(int typeOfEdge, std::string name1, std::string name2){
    Graph::Vertex v1 = Graph::Vertex(name1);
    addVertex(v1);
    Graph::Vertex v2 = Graph::Vertex(name2);
    addVertex(v2);
    v1.setStartToStart(name2);
}

std::ostream& operator<<(std::ostream &os, Graph const& g)
{
    g.printGraph(os);
    return os;
}

void Graph::printGraph(std::ostream &os)const{
    for (unsigned int i = 0; i < vertices.size(); ++i){
        vertices[i].printVertex(os);
    }
}

std::ostream& operator<<(std::ostream &os, Graph::Vertex const& v)
{
    v.printVertex(os);
    return os;
}

void Graph::Vertex::printVertex(std::ostream &os)const{
    os << " vertex : " << idVertex << "\t";
    for (unsigned int i = 0; i < startToStart.size(); ++i){
        os << "startToStart: " << startToStart[i] << "\t";
    }
}

}

【问题讨论】:

  • 只是我的对象中没有任何内容。当我打印我的图表时,我有:6Vertex:Vertex:(->但这里什么都没有,它不显示我的顶点 ID 或我的边列表)我的设置函数或我在类 Graph 和类 Vertex 之间的链接是错误的
  • 除非您显着减小已发布代码的大小,否则我不会期望任何帮助。删除任何不必要的东西,简化然后向我们展示更简单的代码。也许即使在这个过程中你也会找到解决方案。

标签: c++ class methods graph private


【解决方案1】:

您的 Graph 类定义了具有空主体的构造函数,因此这些构造函数将成员默认初始化。

main()中的那一行

Graph g = Graph();

使用默认构造函数创建一个默认构造的Graph(临时)。然后它使用复制构造函数将该临时复制到g

Graph 的默认构造函数和复制构造函数都将对象默认初始化。

解决方案是确保所有构造函数适当地初始化他们正在创建的对象,而不是假设值将被复制。

(以上假设没有编译器优化,例如省略临时文件)。

【讨论】:

  • "您的 Graph 类定义了具有空主体的构造函数,因此这些成员未初始化。" - 这是不真实的。除非我错过了什么,所有成员都有默认构造函数,所以它们不需要显式初始化。
  • 您显然甚至没有费心去阅读 Wojtek 的代码。比如Graph的两个构造函数的定义是Graph::Graph(){}Graph::Graph(Graph const&amp; g){}。这些完全按照我的描述进行。所有的类都有相似的构造函数。
  • Graph::Graph(){} 是可以的,只要Graph() 类只包含一个vector,它会在创建时自动初始化。 copy-ctor 的问题是它不会复制任何东西,只是创建一个空对象,但它仍然会被初始化并且可以安全使用。
  • 好的 - 将“未初始化”一词更改为“默认初始化”。复制时的默认构造会导致更改的值丢失。
  • @Peter 好的,关于复制构造函数,你是对的。我仍然会进一步修改答案,因为成员已初始化 - 只是在复制构造函数中,而不是以预期的方式。所以没有未定义的行为。
【解决方案2】:

这里的问题是addVertex(v1); 会将v1副本 添加到您的vertices 成员向量中,因为这是vector::push_back 所做的。然后你继续修改v1(原来的),但是这个变化不会反映在你的成员变量上(v2也是一样)。您应该在 addEdge 函数的末尾将两个调用移至 addVertex

【讨论】:

  • 只需在更改之后(而不是之前)调用addVertex 即可。指针会增加复杂性。
  • 好的,谢谢,我不知道向量复制对象,我认为它“只是”将对象添加到向量中
  • 啊,既然你不打算使用指针,你可以删除所有的构造函数和析构函数,从而解决彼得指出的问题。
  • 没关系,问题出在我的构造函数和addVertex()的调用上。谢谢
  • addEdge int readDotFile 函数之后还有一个额外的大括号
猜你喜欢
  • 2012-09-15
  • 1970-01-01
  • 2013-06-22
  • 2020-10-13
  • 2014-03-27
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多