如何重载<<运营商打印班级成员?

时间:2016-08-04 18:23:57

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

这是班级

    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()函数工作得很好。我用标记对它们进行了测试。

这是我认为问题存在的地方。这是重载运算符&lt;&lt;

的代码
    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;

现在,该程序编译得很好。但是,在执行时,图表不会被打印。我没有能够以相同的方式打印图形而不会重载运算符,而是让for循环在main中运行或使用类成员函数。

任何人都可以帮助我吗?我正在使用Visual Studio 2015。

3 个答案:

答案 0 :(得分:2)

永远不会输入循环,因为

i < g.size

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

你必须设置它,即

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

此外,您没有指定复制构造函数,因此将使用隐式构造函数。但隐式的只是复制值,因此指针grph将指向2个对象到相同的数据。你泄漏了内存,这就是为什么它并不重要(技术上),但是你应该实现一个正确的析构函数和复制/移动构造函数。

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

答案 1 :(得分:0)

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

添加到您的主管this.size = size应解决您的问题,如Rakete1111已正确指出。

以下方法允许您打印false或true,否则您可以尝试cout<<std::boolalpha flag

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;
    }

答案 2 :(得分:0)

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

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

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

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

  2. 您缺少一个释放图表数据的析构函数。

  3. 您缺少复制构造函数和复制赋值运算符,无法将图形数据从一个graph对象复制到另一个{.p>

  4. 即使您通过引用将graph对象传递给operator<<,您仍然需要正确实施规则三,以避免代码中出现问题。

    您需要:

    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;
      }