【问题标题】:How do I overload the << operator to print a class member?如何重载 << 运算符以打印类成员?
【发布时间】:2016-08-04 18:23:56
【问题描述】:

这是课程

    class graph {
    public:
        graph() {}; // constructor
        graph(int size);
        friend ostream& operator<< (ostream& out, graph g);
    private:
        int size;
        bool** grph;
    };

这就是我生成图表的方式:

    graph::graph(int size) {
        grph = new bool*[size];
        for (int i = 0; i < size; ++i)
            grph[i] = new bool[size];
        for (int i = 0; i < size; ++i)
            for (int j = i; j < size; ++j) {
                if (i == j)
                    grph[i][j] = false;
                else {
                    cout << prob() << endl;//marker
                    grph[i][j] = grph[j][i] = (prob() < 0.19);
                    cout << grph[i][j] << endl;//marker
                }
            }
        cout << "Graph created" << endl;//marker
    }

构造函数和 prob() 函数工作得很好。我已经使用标记对它们进行了测试。

这是我认为存在问题的地方。这是重载运算符 的代码

    ostream& operator<< (ostream& out, graph g) {
        for (int i = 0; i < g.size; ++i) {
            for (int j = 0; j < g.size; ++j) 
                out << g.grph[i][j] << "\t";
            out << endl;
        }
        return out;
    }

这是如何调用的。

     graph g(5);
 cout << g << endl;

现在,程序编译得很好。但是,在执行时,图表没有被打印出来。我已经能够在不重载运算符的情况下以相同的方式打印图形,但是通过在 main 内部运行 for 循环或使用类成员函数。

谁能帮帮我?我正在使用 Visual Studio 2015。

【问题讨论】:

标签: c++ class operator-overloading runtime-error graph-theory


【解决方案1】:

永远不会进入循环,因为

i < g.size

总是false,因为g.size0!您实际上从未将成员变量 size 设置为用户输入的大小,因此它默认为 0

你必须设置它,即

this->size = size; //Sets member variable 'size' to 'size' from the function arguments

另外,您没有指定复制构造函数,因此将使用隐式构造函数。但隐含的只是复制值,因此指针grph 将指向 2 个对象指向相同的数据。您正在泄漏内存,这就是为什么 这无关紧要(技术上),但您应该实现适当的析构函数和复制/移动构造函数。

但是因为operator&lt;&lt; 应该只用于打印,请考虑通过const&amp; 而不是按值传递!

【讨论】:

  • 虽然这只是问题的一部分。查看运算符的签名,然后查看 OP 对类的 c'tors。
  • @NathanOliver 我没看到。他们一样吗?
  • OP 正在制作副本。他们有抄写员吗?
  • @Galik 修复尺寸问题虽然不能解决打印问题,但打印才是问题所在。现在他们将打印浅拷贝,这将(希望)导致访问冲突。
  • @Galik 哎呀。我看错了。这很好,可以回答这个问题。感谢您直言不讳。
【解决方案2】:

问题取决于类属性size的错过初始化 在构造函数方法中。

添加到您的 ctor this.size = size 应该可以解决您的问题,正如 Rakete1111 已经正确指出的那样。

下面的方法可以让你打印false或者true,否则你可以试试cout&lt;&lt;std::boolalphaflag

ostream& operator<< (ostream& out, graph g) {
        for (int i = 0; i < g.size; ++i) {
            for (int j = 0; j < g.size; ++j) 
                out << (g.grph[i][j] ? "true" : "false") << "\t";
            out << endl;
        }
        return out;
    }

【讨论】:

  • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
  • 我看到你的构造函数更好,实际上原因是错过了“size”属性的初始化......
【解决方案3】:

除了其他人所说的(您没有初始化size 成员),您的operator&lt;&lt; 正在接受graph 对象按值。调用运算符时,会生成输入 graph 对象的 copy,但您的 graph 类未正确编写以支持复制。您的operator&lt;&lt; 应该接受graph 对象按常量引用,因此不需要副本:

ostream& operator<< (ostream& out, const graph &g)

您的graph 类不支持复制,因为您完全违反了Rule of Three

  1. 您的默认构造函数根本没有初始化图形数据。

  2. 您缺少释放图形数据的析构函数。

  3. 您缺少复制构造函数和复制赋值运算符来将图形数据从一个 graph 对象复制到另一个对象。

即使您通过引用将graph 对象传递给operator&lt;&lt;,您仍然需要正确实施三法则以避免一般代码中的问题。

您需要:

  1. 实现适当的构造函数和操作符:

    class graph {
    public:
        graph(int size = 0);
        graph(const graph &src);
        ~graph();
    
        graph& operator=(const graph &rhs);
    
        friend std::ostream& operator<< (std::ostream& out, const graph &g);
    private:
        int size;
        bool** grph;
    };
    
    std::ostream& operator<< (std::ostream& out, const graph &g);
    

    graph::graph(int size)
        : grph(NULL), size(size)
    {
        grph = new bool*[size];
        for (int i = 0; i < size; ++i) {
            grph[i] = new bool[size];
        }
        for (int i = 0; i < size; ++i) {
            for (int j = i; j < size; ++j) {
                if (i == j) {
                    grph[i][j] = false;
                } else {
                    grph[i][j] = grph[j][i] = (prob() < 0.19);
                }
            }
        }
    }
    
    graph::graph(const graph &src)
        : grph(NULL), size(src.size)
    {
        grph = new bool*[size];
        for (int i = 0; i < size; ++i) {
            grph[i] = new bool[size];
            for (int j = i; j < size; ++j) {
                grph[i][j] = src.grph[i][j];
        }
    }
    
    graph::~graph() {
        for (int i = 0; i < size; ++i) {
            delete[] grph[i];
        }
        delete[] grph;
    }
    
    graph& graph::operator=(const graph &rhs)
    {
        if (this != &rhs)
        {
            graph tmp(rhs);
            std::swap(grph, tmp.grph);
            std::swap(size, tmp.size);
        }
        return *this;
    }
    
    std::ostream& operator<< (std::ostream& out, const graph &g) {
        for (int i = 0; i < g.size; ++i) {
            for (int j = 0; j < g.size; ++j) {
                out << g.grph[i][j] << "\t";
            }
            out << endl;
        }
        return out;
    }
    
  2. graph 更改为使用std::vector,而不是手动分配数组。让编译器为您处理所有的内存管理和复制:

    class graph {
    public:
        graph(int size = 0);
        friend ostream& operator<< (ostream& out, const graph &g);
    private:
        std::vector<std::vector<bool> > grph;
    };
    
    std::ostream& operator<< (std::ostream& out, const graph &g);
    

    graph::graph(int size)
    {
        grph.resize(size);
        for (int i = 0; i < size; ++i) {
            grph[i].resize(size);
        }
        for (int i = 0; i < size; ++i) {
            for (int j = i; j < size; ++j) {
                if (i == j) {
                    grph[i][j] = false;
                } else {
                    grph[i][j] = grph[j][i] = (prob() < 0.19);
                }
            }
        }
    }
    
    ostream& operator<< (ostream& out, const graph &g) {
        for (int i = 0; i < g.grph.size(); ++i) {
            std:::vector<bool> &row = g.grph[i];
            for (int j = 0; j < row.size(); ++j) {
                out << row[j] << "\t";
            }
            out << endl;
        }
        return out;
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多