简体   繁体   English

c ++类成员函数

[英]c++ classes member functions

With the following code, where the member functions are declared in the class, it prompts the user to enter various inputs like hours and pay. 使用以下代码,在类中声明成员函数,它会提示用户输入各种输入,如小时和付费。

cout << endl << "Now please input info #1" << endl;
Info p1;
cout << endl << "Now please input info #2" << endl;
Info p2;
p2.combineinfo(p1);  /**< combines the info, like hours, pay, ect.  */
printinfo(pnew);  /**< prints out the combined paycheck information  */

The information is put into p1 and p2 accurately because I can confirm with a cout . 准确地将信息放入p1p2因为我可以用cout确认。 However, p2.combineinfo(p1) prompts again for a set of information inputs. 但是, p2.combineinfo(p1)再次提示输入一组信息。 I don't want this, I just need it to pass to this function to get combined and then be printed out with printinfo(); 我不想要这个,我只需要传递给这个函数来组合然后用printinfo();打印出来printinfo(); .

Info Info::combineInfo(Info p1)
{
Info p2;
Info pnew;
pnew.name = p1.name;
pnew.hours = p1.hours + p2.hours;
pnew.total = p1.total + p2.total;
return pnew;
}

Updated Info: 更新信息:

Info::Info()
{
string dummy;
cout << "question here"<<endl;
getline(cin, a);
cout <<"question here"<<endl;
cin >> b;
getline(cin, dummy);
cout <<"question here"<<endl;
cin >> c;
getline(cin, dummy);
cout << "quesiton here"<< endl;
initializeDate(start);
cout << "question here "<< endl;
initializeDate(finish);
}

You don't show it but you are probably asking for the input in the Info constructor. 您没有显示它,但您可能要求Info构造函数中的输入。 Something like: 就像是:

Info::Info()
{
   cout << "Enter name: ";
   cin >> name;
   cout << "Enter hours: ";
   cin >> hours;
   cout << "Enter total: ";
   cin >> total;
}

So in combineInfo you create two objects of class Info, so the constructors run and it asks for input for each one. 因此,在combineInfo中,您可以创建两个Info类对象,因此构造函数会运行并请求每个对象的输入。 Just don't ask for the values in the constructor. 只是不要求构造函数中的值。 Add another method AskForInput to ask for the values and don't call it from the constructor. 添加另一个方法AskForInput来询问值,不要从构造函数中调用它。

i'm guessing you're reading in input froms stdin inside your constructor for Info (could you post this code?). 我猜你正在读取你的构造函数中的stdin输入信息(你可以发布这段代码吗?)。 thus, when you create p2 and pnew again, it's calling that very same code. 因此,当你再次创建p2和pnew时,它会调用相同的代码。

i suggest you have separate code for initializing a variable with stdin, instead of your constructor. 我建议你有单独的代码用于使用stdin而不是你的构造函数初始化变量。 otherwise, there's not much you can do here about it being called! 否则,你在这里打电话的时间并不多!

Since I ended up typing a lot of comments, I've combined it into an answer: 由于我最后输入了很多评论,我将它组合成一个答案:

As per the other answers, your issue is that you are calling Info 's constructors in your combineInfo function, and you are prompting the user in the constructors. 根据其他答案,您的问题是您在combineInfo函数中调用Info的构造函数,并且您在combineInfo函数中提示用户。 It's usually a bad idea to use std::cin inside a constructor - What if you (or your code's users) decide to use the code in a situation where std::cin is inappropriate (eg when you later decide to upgrade to a GUI)? 在构造函数中使用std::cin通常是一个坏主意 - 如果你(或你的代码的用户)决定在std::cin不合适的情况下使用代码怎么办(例如,当你后来决定升级到GUI时)? What if you want to construct the object with pre-determined data? 如果要使用预定数据构造对象,该怎么办? Or in a unit test? 或者在单元测试中?

In fact your own code provides just such an example: you've defined Info in a way that the only way it can be constructed is by asking for info from the user. 实际上,您自己的代码提供了这样一个示例:您已经定义了Info ,其唯一的方法是通过向用户请求信息来构建Info。 However, you have two ways that you actually want to construct the object - (1) by prompting for info from the user, and (2) by combining info which already exists inside two other Info objects ( p1 and p2 ). 但是,您实际上有两种方法可以构建对象 - (1)通过提示来自用户的信息,以及(2)通过组合已存在于其他两个Info对象( p1p2 )中的信息。

The better solution is to have the constructor receive the data via parameters - Info::Info(string name, int hours, int total) , obtain the info from the user outside the class (when appropriate), and pass it in to the constructor. 更好的解决方案是让构造函数通过参数接收数据Info::Info(string name, int hours, int total) ,从类外部的用户(适当时)获取信息,并将其传递给构造函数。

Alternatively, if you're determined to keep the cin code inside the constructor, then do not use a compareInfo() function - make a second constructor which takes two Info objects as parameters, and place your code there: 或者,如果您决定将cin代码保留在构造函数中,那么不要使用compareInfo()函数 - 创建第二个构造函数,它将两个Info对象作为参数,并将代码放在那里:

Info::Info(Info p1, Info p2)
{
    name = p1.name;
    hours = p1.hours + p2.hours;
    total = p1.total + p2.total;
}

Then do your combining like this: 然后像这样组合:

Info pnew(p1, p2);

EDIT: you've commented that have a criterion you must stick to, namely that the combining must happen inside a Info Info::combineInfo(Info) function. 编辑:你已经评论说你必须遵守一个标准,即组合必须在Info Info::combineInfo(Info)函数中发生。 This is awkward because your constructor prompts for information, and you must construct a temporary Info object inside your member function: 这很麻烦,因为构造函数会提示输入信息,您必须在成员函数中构造一个临时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;
}

You have three solutions that I can think of, none one of them particularly attractive (and I am surprised that a teacher would impose this requirement on you): 你有三个我能想到的解决方案,其中没有一个特别有吸引力(我很惊讶老师会对你强加这个要求):

(1) Provide a constructor which does not prompt for info. (1)提供不提示信息的构造函数。 However it must have a different signature to the one which does request info, because you cannot define a default constructor twice: 但是它必须与请求信息的签名具有不同的签名,因为您无法定义两次默认构造函数:

Info::Info()
{
   // Prompt user.
}

Info::Info(int dummyValue)
{
   // Do nothing.
}

Then when you create your pnew object, call the second constructor: Info pnew(0); 然后在创建pnew对象时,调用第二个构造函数: Info pnew(0); .

(2) Do not provide a default constructor at all, instead create one which you inform whether or not to prompt: (2)根本不提供默认构造函数,而是创建一个通知是否提示:

Info::Info(bool prompt)
{
    if (prompt)
    {
        // Construct object by prompting user.
    }
    // No need to do an else, simply do nothing if !prompt
}

This has the disadvantage that you will always have to supply a parameter to construct Info objects: 这样做的缺点是您始终必须提供参数来构造Info对象:

Info p1; // Error, no default constructor
Info p1(true); // Construct by prompting
Info pnew(false); // Construct without prompting

(3) Do not create a temporary pnew at all, just modify p1 and return that. (3)根本不要创建临时的pnew ,只需修改p1并返回即可。 This is poor style, and only works because you have passed p1 by value (therefore you are not modifying the original 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;
}

Other comments: 其他的建议:

You also have a couple of bugs in your code as it stands: 您的代码中还有一些错误:

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.

Change the code to this: 将代码更改为:

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.

The second bug is as follows: 第二个错误如下:

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

This only seems to work correctly for you, because of the constructor issue - you're being prompted to enter the info for combineInfo 's p2 , so it ends up being the same as the p2 you actually intended to use (assuming you entered the same data again), and it seems to combine them correctly. 似乎只适合你,因为构造函数问题 - 你被提示输入combineInfop2 ,所以它最终与你实际打算使用的p2相同(假设你进入了再次使用相同的数据),似乎正确地将它们组合在一起。 Do this instead: 改为:

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 in this case are shorthand for this.hours and this.total . 在这种情况下, hourstotalthis.hoursthis.total简写。

Another thing to consider for future reference, is to overload the + operator instead of writing a combine function: 要考虑将来参考的另一件事是重载+运算符而不是编写组合函数:

Info Info::operator+(Info p1)
{
Info pnew;
pnew.name = p1.name;
pnew.hours = p1.hours + hours;
pnew.total = p1.total + total;
return pnew;
}

Now instead of: 而不是:

Info pnew = p2.combineInfo(p1);

You can write: 你可以写:

Info pnew = p1 + p2;

Finally, consider passing by reference instead of by value - for non-trivial objects it's usually faster for the function to dereference the address instead of making a new copy of it: 最后,考虑通过引用而不是按值传递 - 对于非平凡对象,函数通常更快地取消引用地址而不是创建它的新副本:

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.

EDIT: But don't do this if you use solution 3 above, otherwise you will modify the original p1 which is probably not desireable to you. 编辑:但是如果您使用上面的解决方案3,请不要这样做,否则您将修改可能不希望您的原始p1

Presumably you have decided have the default constructor for Info read in the value. 大概你已经决定在值中读取Info的默认构造函数。 Then in the method combineInfo you again have a couple of constructors which must do the same. 然后在方法combineInfo你又有了几个必须做同样的构造函数。

You can avoid the problem by having a method after construction that prompts for the data. 您可以通过在构造之后使用提示输入数据的方法来避免此问题。 If you show your constructor code that might help. 如果您显示可能有用的构造函数代码。

Having said that, most likely the method ought to read: 话虽如此,该方法很可能应该是:

void Info::combineInfo(const Info& p1)
{
    name = p1.name; // Why not keep p2.name?
    hours += p1.hours;
    total += p1.total;
}

and then call: 然后打电话:

printInfo(p2);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM