在 [over.ass]/2 中的示例中,为什么 *bptr = dobj2;调用 D::operator=(const B&)?

In the example in [over.ass]/2 why does *bptr = dobj2; call D::operator=(const B&)?

[over.ass]/2

我能理解为什么 bptr->operator=(dobj2); 调用 D& operator= (const B&) 以及为什么 dobj1 = dobj2; 调用隐式声明的 D::operator=(const D&)。但我不太确定 *bptr = dobj2;

示例:

struct B {
    virtual int operator= (int);
    virtual B& operator= (const B&);
};
struct D : B {
    virtual int operator= (int);
    virtual D& operator= (const B&);
};

D dobj1;
D dobj2;
B* bptr = &dobj1;
void f() {
    bptr->operator=(99); // calls D::operator=(int)
    *bptr = 99; // ditto
    bptr->operator=(dobj2); // calls D::operator=(const B&)
    *bptr = dobj2; // ditto
    dobj1 = dobj2; // calls implicitly-declared D::operator=(const D&)
}

当你有一个 Base 指针或对派生实例的引用并在其上调用虚拟成员函数时,就会发生多态性。

在你的例子中

bptr->operator=(99); // calls D::operator=(int)
bptr->operator=(dobj2); // calls D::operator=(const B&)

指向派生实例的基指针正在调用虚函数 => 调用多态性 => 将调用派生版本。

*bptr = 99; // ditto
*bptr = dobj2; // ditto

这简直就是

(*bptr).operator=(99);
(*bptr).operator=(dobj2);

或者对派生实例的基引用正在调用虚函数 => 调用多态性 => 将调用派生版本。

dobj1 = dobj2; // calls implicitly-declared D::operator=(const D&)

不再有多态性,因为调用者 (dobj1) 不是 (base) reference/pointer。调用了编译器生成的 D::operator=(const D&) ,它也调用 基数 class 的运算符 = 自动。

virtual B& operator= (const B&);

But I'm not so sure about *bptr = dobj2;.

来自over.match.oper#tab:over.rel.op.func

两者:

*bptr = dobj2; // ditto
dobj1 = dobj2; // calls implicitly-declared D::operator=(const D&)

在上下文中相同,但表示不同:

表达式:

a=b

作为成员函数:

(a).operator= (b)