Image

Imagetyrdinjer wrote in Imagecpp

Inheritance and Assignment Operators

I was doing some experiments with inheritance, and came across something a bit odd.

I have a base class in which the assignment operator is declared private, and is undefined. All member fields are protected, and thus accessible to derived classes.

The derived class adds no new fields. It simply exists to extend the functionality of the base class.

Since the derived class contains no new fields, in theory it should be able to define its assignment operator like this:
derived& derived::operator = (const base &rt);

However, when I tried this, with gcc 4.0.1 on a Mac, anytime I tried to use the assignment operator with the derived class, the compiler would try to use the undefined base class assignment operator. And since this function did not exist, an error would be generated.

Making the base class operator a protected pure virtual function did not alleviate the error.

What finally made the error go away was adding in another assignment operator in the derived class:
derived& derived::operator = (const derived &rt);

Now everything works as expected.

As a side note, I realize that simply declaring the assignment operator in the base class, and making it protected will allow the derived class to use it. However, I was wondering about the behavior. Am I forgetting some silly rule of inheritance?


This one does not compile This one compiles / works. I am curious as to why adding the extra assignment operator helps. This one also compiles / works, which is unsurprising, since this is the standard way to do it.

#include <iostream>
class base1
    {
    public:
        base1(const base1 &b)
            : number(b.number)
            {}
        virtual ~base1()
            {}
        int getNum() const
            {
            return number;
            }
    protected:
        base1(int newNumber)
            : number(newNumber)
            {}
        int number;

    private:
        base1();
        base1& operator = (const base1&);
    };
class derived1 : public base1
    {
    public:
        derived1(int newNumber)
            : base1(newNumber)
            {}
        derived1& operator = (const base1 &b)
            {
            number = b.getNum();
            return *this;
            }
    };
int main ()
    {
    derived1 a(5), b(6);
    std::cout << "a: " << a.getNum() <<
        "    b: " << b.getNum() << "\n";
    a = b;
    std::cout << "a: " << a.getNum() <<
        "    b: " << b.getNum() << "\n";
    return 0;
    }


#include <iostream>
class base2
    {
    public:
        base2(const base2 &b)
            : number(b.number)
            {}
        virtual ~base2()
            {}
        int getNum() const
            {
            return number;
            }
    protected:
        base2(int newNumber)
            : number(newNumber)
            {}
        int number;

    private:
        base2();
        base2& operator = (const base2&);
    };
class derived2 : public base2
    {
    public:
        derived2(int newNumber)
            : base2(newNumber)
            {}
        derived2& operator = (const base2 &b)
            {
            number = b.getNum();
            return *this;
            }
        derived2& operator = (const derived2 &d)
            {
            number = d.number;
            return *this;
            }
    };
int main ()
    {
    derived2 a(5), b(6);
    std::cout << "a: " << a.getNum() <<
        "    b: " << b.getNum() << "\n";
    a = b;
    std::cout << "a: " << a.getNum() <<
        "    b: " << b.getNum() << "\n";
    return 0;
    }



#include <iostream>
class base3
    {
    public:
        base3(const base3 &b)
            : number(b.number)
            {}
        virtual ~base3()
            {}
        int getNum() const
            {
            return number;
            }
    protected:
        base3(int newNumber)
            : number(newNumber)
            {}
        base3& operator = (const base3 &b)
            {
            number = b.number;
            return *this;
            }
        int number;

    private:
        base3();
    };
class derived3 : public base3
    {
    public:
        derived3(int newNumber)
            : base3(newNumber)
            {}
    };
int main ()
    {
    derived3 a(5), b(6);
    std::cout << "a: " << a.getNum() <<
        "    b: " << b.getNum() << "\n";
    a = b;
    std::cout << "a: " << a.getNum() <<
        "    b: " << b.getNum() << "\n";
    return 0;
    }