我无法理解以下功能的原因和方式:
personType& setLastName(string last);
personType& setFirstName(string first);
这是D.S.Malik的“使用C ++进行数据结构”一书中的解决方案。使用这些函数,输出是“Brad Pitt”,这是正确的。但是,解释根本不满足我。你能解释为什么以及如何运作吗?
我试着自己了解一段时间。这就是我做的。我改变了以下函数,并保持main.cpp相同
personType setLastName(string last) { lastName=last; return *this; }
personType setFirstName(string first); { firstName=first; return *this; }
p1.print()只打印“Brad”。所以这是不正确的。问题是为什么?
现在我要做以下事情。而不是写
p1.setLastName("Brad").setFirstName("Pitt");
和以前一样,我将这一行分为两个步骤:
p1.setLastName("Brad");
p1.setFirstName("Pitt")
现在p1.print()根据需要输出“Brad Pitt”。和以前一样,我想知道为什么会这样。
提前感谢您的时间和帮助。
标题文件:
#ifndef personType_H
#define personType_H
#include <iostream>
#include <string>
using namespace std;
class personType
{
public:
personType();
personType(string first, string last);
void print() const;
void setName(string first, string last);
string getFirstName() const;
string getLastName() const;
personType& setLastName(string last);
personType& setFirstName(string first);
private:
string firstName;
string lastName;
};
#endif // !personType_H
实现类的cpp文件:
#include "stdafx.h"
#include "personType.h"
personType::personType()
{
firstName = "";
lastName = "";
}
personType::personType(string first, string last)
{
setName(first, last);
}
void personType::print() const
{
cout << firstName << " " << lastName << endl;
}
void personType::setName(string first, string last)
{
firstName = first;
lastName = last;
}
string personType::getFirstName() const
{
return firstName;
}
string personType::getLastName() const
{
return lastName;
}
personType& personType::setLastName(string last)
{
lastName = last;
return *this;
}
personType& personType::setFirstName(string first)
{
firstName = first;
return *this;
}
的main.cpp
int main()
{
personType p1;
p1.setLastName("Brad").setFirstName("Pitt");
p1.print();
return 0;
}
答案 0 :(得分:3)
如果您没有返回引用,那么
return *this;
制作对象的副本并返回该对象。使用以下链接进行链接:
p1.setLastName("Brad").setFirstName("Pitt");
您在副本上呼叫setFirstName()
,而不是p1
。这就是p1.print()
确实显示新名字的原因。它相当于:
personType temp = p1.setLastName("Brad");
temp.setFirstName("Pitt");
p1.print();
新名字位于temp
,而不是p1
。要查看这两项更改,您需要执行以下操作:
temp.print();
答案 1 :(得分:2)
正如您所做的那样,您的setLastname和setFirstName会返回正在调用它的对象的副本。通过返回引用,您将返回对象本身。因此,当您返回副本并执行
时person.setFirstname("brad").setSecondname("pitt");
评估为:
Person p = person.setFirstname("brad); //note: not the original person! a copy of person!
p.setSecondname("pitt");
所以现在你有两个人。一个只有它的名字设置,一个只有第二个名字设置。但是,正如在这个答案的评论中指出的那样,我在示例代码中称为“p”的第二个对象从未存储在任何地方,因此会立即被销毁。
答案 2 :(得分:1)
来自Bjarne Stroustrup的 “C ++编程语言” (第三版)。 第10.2.7节自我引用[class.this]:
状态更新功能
add_year()
,add_month()
和add_day()
被定义为不返回值。对于这样一套 相关的更新函数,返回引用通常很有用 更新的对象,以便可以链接操作。例如, 我们想写void f(Date& d) { // ... d.add_day(1).add_month(1).add_year(1); // ... }
向
的引用d
添加一天,一个月和一年。为此,必须声明每个函数以返回对Date
:class Date { // ... Date& add_year(int n); // add n years Date& add_month(int n); // add n months Date& add_day(int n); // add n days };
每个( 非静态 )成员函数都知道调用它的对象,并且可以明确地引用它。例如:
Date& Date::add_year(int n) { if (d == 29 && m == 2 && !leapyear(y + n)) { // beware of February 29 d = 1; m = 3; } y += n; return *this; }
表达式
*this
指的是调用成员函数的对象。 [...]
答案 3 :(得分:0)
通过返回对自己的引用,允许方法链接:
以参考方式返回时,请:
p1.setLastName("Brad").setFirstName("Pitt");
相当于:
p1.setLastName("Brad");
p1.setFirstName("Pitt");
按值返回时,您创建一个副本,然后在此副本上调用第二个方法,然后销毁该方法,因为您从未将其分配给任何内容。
此:
p1.setLastName("Brad").setFirstName("Pitt");
相当于:
p1.setLastName("Brad");
Person(p1).setFirstName("Pitt"); // create a temporary Person object that's instantly destroyed on the next line
答案 4 :(得分:0)
两个不返回对personType的引用的函数,首先将调用对象的#(s,1)lastName设置为参数,然后返回personType对象的 copy 。 personType setLastName(string last){lastName = last;返回*这个; } personType setFirstName(string first); {firstName = first;返回*这个; }
因此,使用这些函数不会修改p1
p1.setLastName("Brad").setFirstName("Pitt");
它基本上变成了
personType copy = p1.setLastName("Brad")
copy.setFirstName("Pitt");
更改返回类型将返回对调用对象(p1)的引用,然后可以调用该引用来修改其内容。
personType& setLastName(string last) { lastName=last; return *this; }
personType& setFirstName(string first); { firstName=first; return *this; }
因此,使用这些函数不会修改p1
p1.setLastName("Brad").setFirstName("Pitt");
它基本上变成了
p1 = p1.setLastName("Brad")
p1.setFirstName("Pitt");
请注意,我基本上是这样说的,我的意思是它会以类似的方式表现。