我有以下类接口:
class Time
{
public:
Time( int = 0, int = 0, int = 0 );
Time &setHour( int );
Time &setMinute( int );
Time &setSecond( int );
private:
int hour;
int minute;
int second;
};
实现在这里:
Time &Time::setHour( int h )
{
hour = ( h >= 0 && h < 24 ) ? h : 0;
return *this;
}
Time &Time::setMinute( int m )
{
minute = ( m >= 0 && m < 60 ) ? m : 0;
return *this;
}
Time &Time::setSecond( int s )
{
second = ( s >= 0 && s < 60 ) ? s : 0;
return *this;
}
在我的主。cpp文件中,我有以下代码:
int main()
{
Time t;
t.setHour( 18 ).setMinute( 30 ).setSecond( 22 );
return 0;
}
怎么可能把这些函数调用链在一起?我不明白为什么会这样
这个正确工作的原因是,当您调用
t.setHour( 18 )
返回值是一个Time&
,一个Time
对象的引用。更重要的是,它被定义为
Time &Time::setHour( int h )
{
hour = ( h >= 0 && h < 24 ) ? h : 0;
return *this; // <--- right here
}
在成员函数内部,this
是调用对象的指针,*this
是调用对象的引用(接收者对象)。这意味着当您调用setHour
时,该函数将在时间上设置小时,然后返回对您进行调用的Time
对象的引用。这样,t.setHour( 18 )
既设置了时间,又返回了对接收者对象的引用。这样,你就可以写
t.setHour( 18 ).setMinute( 30 ).setSecond( 22 );
因为它被解释为
((t.setHour( 18 )).setMinute( 30 )).setSecond( 22 );
,函数返回对t
的引用。
更一般地说,任何时候一个函数返回一个引用,而这个引用是*this
,你对函数返回值执行的任何操作都与你对对象本身执行的操作是无法区分的。
希望这对你有帮助!
t的每个方法都返回一个对t的引用。引用是别名。如果你做了
Time t;
Time& tAgain = t;
tAgain.setMinute( 30 );
tAgain.setMinute
也可以改变t的时间。
现在将这个简单的例子外推到级联。t的每个方法返回对自身的引用
Time &Time::setSecond( int s )
{
second = ( s >= 0 && s < 60 ) ? s : 0;
return *this;
}
所以在表达式中:
t.setHour( 18 ).setMinute( 30 )
t.setHour( 18 )
对t调用setHour,然后返回对t的引用。在这种情况下,引用是临时的。因此,您可以将其视为在对setHour求值时将上面的行改为以下内容:
tAgain.setMinute(30);
t。setHour返回一个引用——类似于上面的tAgain。只是t本身的别名
由于每个函数返回this object对象的引用(the return *this)。
基本上,这意味着每次调用函数时,它都会进行相关的更改,然后将整个对象作为引用传递出去。然后可以对返回的对象进行调用。
也可以这样写:
Time t;
Time& t1 = t.setHour( 18 ); // t1 will refer to the same object as t.
Time& t2 = t1.setMinute( 30 ); // t2 will refer to the same object as t1 and t.
Time& t3 = t2.setSecond( 22 ); // t3 will refer to the same object as t2, t1 and t.
这与重载流操作符类似。
ostream& operator<<(ostream& s, const T& val)
{
s << val;
return s;
}
这样做是因为您修改了流并返回它,以便可以在需要时在下一个级联调用中使用它。它一直通过引用传递,所以它可以继续进入下一个表达式段。
比你们好:
std::cerr << 1 << 2 << 3 << std::endl;
工作!:)
如果您考虑一次一步地解决语句,可能会有所帮助。
以以下内容为例:
x = 1 + 2 * 3 - 4;
x = 1 + 6 - 4;
x = 7 - 4;
x = 3;
c++对函数调用和在语句中执行的其他操作也做同样的处理,按照操作符优先级的顺序求解语句中的每个元素。所以你可以把你的例子想成是用同样的方式解决的:
t.setHour( 18 ).setMinute( 30 ).setSecond( 22 );
t.setMinute( 30 ).setSecond( 22 ); // hour is now set to 18
t.setSecond( 22 ); // minute is now set to 30
t; // seconds now set to 22
如果你返回this
而不是*this
,从而返回指针而不是引用,你会得到同样的效果,除了你用->
代替.
(只是作为一个例子,你通过使用引用来做正确的事情)。以同样的方式,如果您返回一个指向不同的对象的指针或引用,您也可以对它做同样的事情。例如,假设您有一个返回Time
对象的函数。
class Time{
public:
int getSeconds(){
return seconds;
};
int seconds;
};
Time getCurrentTime(){
Time time = doSomethingThatGetsTheTime();
return time;
};
int seconds = getCurrentTime().getSeconds();
您无需将语句拆分为两个不同的语句或创建一个临时变量来保存返回的Time对象,即可获得秒数。
c++: Using '
这种技术称为方法链接。在您给出的示例中,所有方法都返回相同的对象(this),因此它们都影响相同的对象。这种情况并不罕见,但知道这种情况并不一定是这样是很有用的;链中的一些或全部方法可以返回不同的对象。例如,您可能还拥有如下方法:
Date Time::date() const;
String Date::dayOfWeek() const;
在这种情况下,你可以说:
Time t;
String day = t.date().dayOfWeek();
获取星期几的名称。在这种情况下,t.date()
返回一个Date对象,用于调用dayOfWeek()
。
因为当函数执行并返回时,它返回对自身的引用,因此它可以再次调用functions