码农公寓

c – 对抽象类和`decltype`的L值引用

2024-03-18 13:35:10

我提出了下面这段代码,认为它不会起作用,但令我惊讶的是它完全没问题,我想要一些解释.

#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给出左值引用.