我提出了下面这段代码,认为它不会起作用,但令我惊讶的是它完全没问题,我想要一些解释.
#include <cstdio>
#include <algorithm>
struct Abstract
{
Abstract()
{ printf("\tConstructing Abstract instance.\n"); }
virtual const char* name() const =0;
auto talk() const -> decltype(*this)
{
printf("My name is %s.\n",name());
return *this;
}
};
struct Concrete
: public Abstract
{
Concrete()
{ printf("\tConstructing Concrete instance.\n"); }
const char* name() const
{ return "Bond"; }
};
int main()
{
Concrete C;
printf("James %s.\n",C.talk().name());
}
此代码的输出是:
Constructing Abstract instance.
Constructing Concrete instance.
My name is Bond.
James Bond.
Q1(这是对C 11的非特异性,只需删除decltype并用const Abstract&替换auto).为什么编译器接受语法C.talk().name()?
除非我弄错了,我认为表达式C.talk()可以是prvalue(Abstract的副本,不是因为只有一个构造函数输出的情况)或左值引用,在这种情况下我不确定是什么因为对我来说,对抽象类的左值引用似乎也不可能.
Q2这引出了第二个问题:decltype如何“知道”返回某种引用,而不是一个简单的值?
解决方法:
Q1:不仅允许对抽象类进行左值引用,而且实际上多态性必不可少.请注意,引用类型对应于表达式的静态类型,而不是对象的动态类型,当然它不能是抽象类(实际上,这也不完全正确,但它足够接近于此目的)回答).
因此,语法C.talk().name()被接受,因为Abstract类型包含成员函数name()的声明,并且它将被正确执行,因为在执行时,实际调用的函数取决于动态类型,这是具体的,并具有name()的实现.
Q2:*这是左值表达式,左值表达式的decltype给出左值引用.