协变虚函数的 C++ 规则

C++ rules for covariant virtual function

我正在阅读 Covariant virtual function。它说

假设B::f覆盖了虚函数A::f。如果满足以下所有条件,A::f 和 B::f 的 return 类型可能会有所不同:

1) The const or volatile qualification of the pointer or reference returned by B::f has the same or less const or volatile qualification of the pointer or reference returned by A::f.

2) A::f returns an lvalue reference if and only if B::f returns an lvalue reference.

3) The function B::f returns a pointer or a reference to a class of type T, and A::f returns a pointer or a reference to an unambiguous direct or indirect base class of T.

4) The return type of B::f must be complete at the point of declaration of B::f, or it can be of type B

谁能举出合适的例子来解释以上两条规则?这两条规则到底是什么意思?第二条规则是否适用于 C++11? 以下示例是否满足我在这里所说的第一条规则?

#include <iostream>
class Base {
    public:
        virtual const Base& fun() const
        {
            std::cout<<"fun() in Base\n";
            return *this;
        }
        virtual ~Base()
        { }
    private:
        int a=3;
};
class Derived : public Base
{
        const Derived& fun() const
        {
            std::cout<<"fun() in Derived\n";
            return *this;
        }
};
int main(){
    Base* p=new Derived();
    p->fun();
    delete p;
    return 0;
}

如果我错了请指正somewhere.I 对前 2 条规则感到困惑。

谢谢

非常感谢您的帮助。

第一条规则意味着如果 A 版本,您不能将覆盖函数 return 设为具有 constvolatileB没有:

struct A
{
    virtual A* foo() { return new A{}; }    
};

struct B : A
{
    B* foo() override {return new B{}; }          //valid
    const B* foo() override {return new B{}; }    //invalid
    volatile B* foo() override {return new B{}; } //invalid
};

如果考虑调用站点,这是有道理的:

A* my_b = new B{};
A* new_b = my_b->foo(); //discards the const qualifier if B::foo() returns const B*

第二条规则意味着您不能将不同的引用或指针类型作为协变 return 类型。使用与上面相同的示例:

struct A
{
    virtual A* foo() { return new A{}; }    
};

struct B : A
{
    B* foo() override {return new B{}; }   //valid
    B& foo() override {return new B{}; }   //invalid
    B&& foo() override {return new B{}; }  //invalid
};

再想想调用站点:

A* my_b = new B{};
A* new_b = my_b->foo(); //if B::foo() returns a reference, this line is syntactically ill-formed

您的示例满足这两个规则,因为两个 return 类型具有相同的 cv 限定并且都是左值引用。