在C++中继承operator =的麻烦

And*_*man 17 c++ inheritance abstract-class operator-keyword

我遇到了operator =的继承问题.为什么这段代码不起作用,解决它的最佳方法是什么?

#include <iostream>

class A
{
public:
    A & operator=(const A & a)
    {
        x = a.x;
        return *this;
    }

    bool operator==(const A & a)
    {
        return x == a.x;
    }

    virtual int get() = 0; // Abstract

protected:
    int x;
};

class B : public A
{
public:
    B(int x)
    {
        this->x = x;
    }

    int get()
    {
        return x;
    }
};

class C : public A
{
public:
    C(int x)
    {
        this->x = x;
    }

    int get()
    {
        return x;
    }
};

int main()
{
    B b(3);
    C c(7);
    printf("B: %d C: %d B==C: %d\n", b.get(), c.get(), b==c);

    b = c; // compile error
    // error: no match for 'operator= in 'b = c'
    // note: candidates are B& B::operator=(const B&)

    printf("B: %d C: %d B==C: %d\n", b.get(), c.get(), b==c);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 31

如果未在类中声明复制赋值运算符,编译器将隐式声明一个.隐式声明的复制赋值运算符将隐藏任何继承的赋值运算符(在C++中读取"名称隐藏"),这意味着任何继承的赋值运算符将对非限定名称查找过程变为"不可见" (当您这样做时会发生这种情况b = c) ,除非你采取具体步骤"取消隐藏"它们.

在您的情况下,类B没有显式声明的复制赋值运算符.这意味着编译器将声明

B& B::operator =(const B&)
Run Code Online (Sandbox Code Playgroud)

含蓄.它将隐藏继承的运算符A.这条线

b = c;
Run Code Online (Sandbox Code Playgroud)

不编译,因为,这里唯一的候选者是上面隐式声明的B::operator =(编译器已经告诉过你); 所有其他候选人都隐藏了.由于c不可转换B&,上述赋值不会编译.

如果您希望编译代码,可以使用using-declaration取消隐藏A::operator =通过添加继承的代码

using A::operator =;
Run Code Online (Sandbox Code Playgroud)

到了类的定义B.代码现在将编译,虽然它不是一个好的样式.您必须记住,在这种情况下,b = c将调用赋值A::operator =,它仅分配A所涉及对象的部分.(但显然这是你的意图.)

或者,在这种情况下,您始终可以使用名称的限定版本来解决名称隐藏问题

b.A::operator =(c);
Run Code Online (Sandbox Code Playgroud)