由于我最终输入了很多评论,因此我将其合并为一个答案:
根据其他答案,您的问题是您Info
在函数中调用构造combineInfo
函数,并且在构造函数中提示用户。在构造函数中使用通常是个坏主意std::cin
- 如果您(或您的代码的用户)决定在std::cin
不合适的情况下使用代码(例如,当您后来决定升级到 GUI 时)怎么办?如果你想用预先确定的数据构造对象怎么办?还是在单元测试中?
事实上,您自己的代码提供了这样一个示例:您已经定义Info
了一种方式,即构建它的唯一方式是向用户询问信息。但是,您有两种实际想要构造对象的方法 - (1) 通过提示用户输入信息,以及 (2) 通过组合已经存在于其他两个Info
对象 (p1
和p2
) 中的信息。
更好的解决方案是让构造函数通过参数 - 接收数据Info::Info(string name, int hours, int total)
,从类外的用户获取信息(适当时),并将其传递给构造函数。
或者,如果您决定将cin
代码保留在构造函数中,则不要使用compareInfo()
函数 - 创建第二个构造函数,它将两个Info
对象作为参数,并将代码放在那里:
Info::Info(Info p1, Info p2)
{
name = p1.name;
hours = p1.hours + p2.hours;
total = p1.total + p2.total;
}
然后像这样进行组合:
Info pnew(p1, p2);
编辑:您已经评论说必须遵守一个标准,即组合必须发生在Info Info::combineInfo(Info)
函数内部。这很尴尬,因为您的构造函数会提示输入信息,并且您必须在成员函数内构造一个临时Info
对象:
Info Info::combineInfo(Info p1)
{
Info pnew; // Temporary Info object
pnew.name = p1.name;
pnew.hours = p1.hours + hours;
pnew.total = p1.total + total;
return pnew;
}
你有我能想到的三个解决方案,没有一个特别有吸引力(我很惊讶老师会把这个要求强加给你):
(1) 提供一个不提示输入信息的构造函数。但是,它必须具有与请求信息的签名不同的签名,因为您不能两次定义默认构造函数:
Info::Info()
{
// Prompt user.
}
Info::Info(int dummyValue)
{
// Do nothing.
}
然后,当您创建pnew
对象时,调用第二个构造函数:Info pnew(0);
.
(2) 根本不提供默认构造函数,而是创建一个您告知是否提示的构造函数:
Info::Info(bool prompt)
{
if (prompt)
{
// Construct object by prompting user.
}
// No need to do an else, simply do nothing if !prompt
}
这样做的缺点是您必须始终提供一个参数来构造 Info 对象:
Info p1; // Error, no default constructor
Info p1(true); // Construct by prompting
Info pnew(false); // Construct without prompting
(3)根本不要创建临时pnew
文件,只需修改p1
并返回它。这是一种糟糕的风格,只有在您p1
按值传递时才有效(因此您没有修改原始的p1
):
Info Info::combineInfo(Info p1)
{
// No need to do anything with name since it's p1's name you want anyway
p1.hours += hours;
p1.total += total;
return p1;
}
其他的建议:
您的代码中还有几个错误:
cout << endl << "Now please input info #1" << endl;
Info p1;
cout << endl << "Now please input info #2" << endl;
Info p2;
p2.combineinfo(p1); // You are not saving the return value.
printinfo(pnew); // pnew does not exist, see above.
将代码更改为:
cout << endl << "Now please input info #1" << endl;
Info p1;
cout << endl << "Now please input info #2" << endl;
Info p2;
Info pnew = p2.combineinfo(p1); // Now you are saving the result.
printinfo(pnew); // pnew now exists.
第二个错误如下:
Info Info::combineInfo(Info p1)
{
Info p2; // You're creating a new p2 object, this is
// NOT the p2 you called the function on.
Info pnew;
pnew.name = p1.name;
pnew.hours = p1.hours + p2.hours; // Wrong p2
pnew.total = p1.total + p2.total; // Wrong p2
return pnew;
}
由于构造函数问题,这似乎只对您正常工作 - 系统会提示您输入combineInfo
's的信息p2
,因此它最终与p2
您实际打算使用的相同(假设您再次输入相同的数据),并且似乎正确地组合了它们。改为这样做:
Info Info::combineInfo(Info p1)
{
// Info p2; // Delete this line
// your intended p2 is passed to the function as the implicit parameter.
Info pnew;
pnew.name = p1.name;
pnew.hours = p1.hours + hours; // hours refers to implicit parameter
pnew.total = p1.total + total; // total refers to implicit parameter
return pnew;
}
hours
在这种情况下,是 and的total
简写。this.hours
this.total
供将来参考的另一件事是重载+
运算符而不是编写组合函数:
Info Info::operator+(Info p1)
{
Info pnew;
pnew.name = p1.name;
pnew.hours = p1.hours + hours;
pnew.total = p1.total + total;
return pnew;
}
现在代替:
Info pnew = p2.combineInfo(p1);
你可以写:
Info pnew = p1 + p2;
最后,考虑通过引用而不是值传递 - 对于非平凡的对象,函数取消引用地址而不是制作它的新副本通常更快:
Info Info::combineInfo(const Info& p1); // p1 passed by reference
// const replicates the behaviour
// of pass by value whereby
// you cannot accidentally modify
// the original object.
编辑:但是如果您使用上面的解决方案 3,请不要这样做,否则您将修改您p1
可能不希望的原始文件。