Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
92 views
in Technique[技术] by (71.8m points)

Trouble with inheritance of operator= in C++

I'm having trouble with the inheritance of operator=. Why doesn't this code work, and what is the best way to fix it?

#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
", 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
", b.get(), c.get(), b==c);
    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you do not declare copy-assignment operator in a class, the compiler will declare one for you implicitly. The implicitly declared copy-assignment operator will hide any inherited assignment operators (read about "name hiding" in C++), meaning that any inherited assignment operators will become "invisible" to the unqualified name lookup process (which is what happens when you do b = c), unless you take specific steps to "unhide" them.

In your case, class B has no explicitly declared copy-assignment operator. Which mean that the compiler will declare

B& B::operator =(const B&)

implicitly. It will hide the operator inherited from A. The line

b = c;

does not compile, because, the only candidate here is the above implicitly declared B::operator = (the compiler told you about that already); all other candidates are hidden. And since c is not convertible to B&, the above assignment does not compile.

If you want your code to compile, you can use using-declaration to unhide the inherited A::operator = by adding

using A::operator =;

to the definition of class B. The code will now compile, although it won't be a good style. You have to keep in mind that in this case the b = c assignment will invoke A::operator =, which assigns only the A portions of the objects involved. (But apparently that is your intent.)

Alternatively, in cases like this you can always work around name hiding by using a qualified version of the name

b.A::operator =(c);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...