引用为返回类型

时间:2018-03-23 19:08:43

标签: c++ pointers reference

我无法理解以下功能的原因和方式:

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

5 个答案:

答案 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");

请注意,我基本上是这样说的,我的意思是它会以类似的方式表现。