如何重载 << 运算符以打印 class 成员?
How do I overload the << operator to print a class member?
这是class
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 循环 运行 或使用 class 成员函数。
谁能帮帮我?我正在使用 Visual Studio 2015.
永远不会进入循环,因为
i < g.size
总是false
,因为g.size
是0
!您实际上从未将成员变量 size
设置为用户输入的大小,因此它默认为 0
.
你必须设置它,即
this->size = size; //Sets member variable 'size' to 'size' from the function arguments
此外,您没有指定复制构造函数,因此将使用隐式构造函数。但是隐式的只是复制值,所以指针 grph
将指向 2 个对象相同的数据。你正在泄漏内存,这就是为什么这无关紧要(技术上),但你应该实现一个适当的析构函数和 copy/move 构造函数。
但是因为operator<<
应该只打印,考虑按const&
而不是按值传递!
问题是 class 属性没有初始化 size
在构造方法中。
添加到你的 ctor 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;
}
除了其他人所说的(你没有初始化 size
成员),你的 operator<<
正在接受 graph
对象 按值。调用运算符时,会生成输入 graph
对象的 copy,但您的 graph
class 未正确编写以支持复制。您的 operator<<
应该接受 graph
对象 by const reference 而不是因此不需要副本:
ostream& operator<< (ostream& out, const graph &g)
您的graph
class不支持复制,因为您完全违反了Rule of Three:
您的默认构造函数根本没有初始化图形数据。
您缺少释放图形数据的析构函数。
您缺少复制构造函数和复制赋值运算符,无法将图形数据从一个 graph
对象复制到另一个对象。
即使您通过引用将 graph
对象传递给 operator<<
,您仍然需要正确实施三原则以避免代码出现问题。
您需要:
实施适当的构造函数和运算符:
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;
}
更改 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;
}
这是class
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 循环 运行 或使用 class 成员函数。
谁能帮帮我?我正在使用 Visual Studio 2015.
永远不会进入循环,因为
i < g.size
总是false
,因为g.size
是0
!您实际上从未将成员变量 size
设置为用户输入的大小,因此它默认为 0
.
你必须设置它,即
this->size = size; //Sets member variable 'size' to 'size' from the function arguments
此外,您没有指定复制构造函数,因此将使用隐式构造函数。但是隐式的只是复制值,所以指针 grph
将指向 2 个对象相同的数据。你正在泄漏内存,这就是为什么这无关紧要(技术上),但你应该实现一个适当的析构函数和 copy/move 构造函数。
但是因为operator<<
应该只打印,考虑按const&
而不是按值传递!
问题是 class 属性没有初始化 size
在构造方法中。
添加到你的 ctor 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;
}
除了其他人所说的(你没有初始化 size
成员),你的 operator<<
正在接受 graph
对象 按值。调用运算符时,会生成输入 graph
对象的 copy,但您的 graph
class 未正确编写以支持复制。您的 operator<<
应该接受 graph
对象 by const reference 而不是因此不需要副本:
ostream& operator<< (ostream& out, const graph &g)
您的graph
class不支持复制,因为您完全违反了Rule of Three:
您的默认构造函数根本没有初始化图形数据。
您缺少释放图形数据的析构函数。
您缺少复制构造函数和复制赋值运算符,无法将图形数据从一个
graph
对象复制到另一个对象。
即使您通过引用将 graph
对象传递给 operator<<
,您仍然需要正确实施三原则以避免代码出现问题。
您需要:
实施适当的构造函数和运算符:
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; }
更改
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; }