Inheriting overloaded operators

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andy Jarrell

    Inheriting overloaded operators

    I'm trying to inherit from a specific class that has an overloaded operator. The problem I'm getting is that certain
    overloaded operators don't seem to come with the inheritance. For example:

    // TestA.h ---------------------------------------

    #include <iostream>

    enum Aval
    {
    FIRST_VALUE,
    SECOND_VALUE,
    THIRD_VALUE
    };

    class A
    {
    private:
    Aval value;

    public:
    A()
    {
    value = Aval(0);
    std::cout << "A() constructor" << std::endl;
    }

    A( Aval val ) : value(val)
    {
    std::cout << "A(val) constructor" << std::endl;
    }
    virtual ~A();

    virtual A & operator=( const A & otherError );
    virtual A & operator=( const Aval & otherValue );

    virtual Aval GetValue() { return value; }
    };


    // TestA.cpp --------------------------------------

    #include "TestA.h"
    #include <iostream>

    A::~A()
    {
    std::cout << "A destructed" << std::endl;
    }

    A & A::operator=( const A & otherError )
    {
    // Check for self-assignment
    if (this == &otherError)
    {
    return *this;
    }

    value = otherError.valu e;
    return *this;
    }


    A & A::operator=( const Aval & otherValue )
    {
    value = otherValue;
    return *this;
    }

    // Test B.h --------------------------------------

    #include "TestA.h"
    #include <iostream>


    class B : public A
    {
    public:
    B()
    {
    std::cout << "B() constructor" << std::endl;
    }

    virtual ~B()
    {
    std::cout << "B destructed" << std::endl;
    }

    };


    // main.cpp --------------------------------------

    int main( int argc, char* argv[] )
    {
    A testA;
    B testB;

    testA = FIRST_VALUE;
    testB = SECOND_VALUE;

    return 0;
    }


    When compiling this in VC++ 6.0, I get the error for the "testB = SECOND_VALUE" line of code:

    error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'enum Aval' (or there is no
    acceptable conversion).

    The "testA = FIRST_VALUE" seems to be fine. Is this a VC++ 6.0 quirk or am I doing something wrong? Why won't B
    inherit the overloaded operator?

    Thanks.


  • Victor Bazarov

    #2
    Re: Inheriting overloaded operators

    "Andy Jarrell" <andyj@dacaudio .com> wrote...[color=blue]
    > I'm trying to inherit from a specific class that has an overloaded[/color]
    operator. The problem I'm getting is that certain[color=blue]
    > overloaded operators don't seem to come with the inheritance. For[/color]
    example:[color=blue]
    >
    > // TestA.h ---------------------------------------
    >
    > #include <iostream>
    >
    > enum Aval
    > {
    > FIRST_VALUE,
    > SECOND_VALUE,
    > THIRD_VALUE
    > };
    >
    > class A
    > {
    > private:
    > Aval value;
    >
    > public:
    > A()
    > {
    > value = Aval(0);
    > std::cout << "A() constructor" << std::endl;
    > }
    >
    > A( Aval val ) : value(val)
    > {
    > std::cout << "A(val) constructor" << std::endl;
    > }
    > virtual ~A();
    >
    > virtual A & operator=( const A & otherError );
    > virtual A & operator=( const Aval & otherValue );
    >
    > virtual Aval GetValue() { return value; }
    > };
    >
    >
    > // TestA.cpp --------------------------------------
    >
    > #include "TestA.h"
    > #include <iostream>
    >
    > A::~A()
    > {
    > std::cout << "A destructed" << std::endl;
    > }
    >
    > A & A::operator=( const A & otherError )
    > {
    > // Check for self-assignment
    > if (this == &otherError)
    > {
    > return *this;
    > }
    >
    > value = otherError.valu e;
    > return *this;
    > }
    >
    >
    > A & A::operator=( const Aval & otherValue )
    > {
    > value = otherValue;
    > return *this;
    > }
    >
    > // Test B.h --------------------------------------
    >
    > #include "TestA.h"
    > #include <iostream>
    >
    >
    > class B : public A
    > {
    > public:
    > B()
    > {
    > std::cout << "B() constructor" << std::endl;
    > }
    >
    > virtual ~B()
    > {
    > std::cout << "B destructed" << std::endl;
    > }
    >
    > };
    >
    >
    > // main.cpp --------------------------------------
    >
    > int main( int argc, char* argv[] )
    > {
    > A testA;
    > B testB;
    >
    > testA = FIRST_VALUE;
    > testB = SECOND_VALUE;
    >
    > return 0;
    > }
    >
    >
    > When compiling this in VC++ 6.0, I get the error for the "testB =[/color]
    SECOND_VALUE" line of code:[color=blue]
    >
    > error C2679: binary '=' : no operator defined which takes a right-hand[/color]
    operand of type 'enum Aval' (or there is no[color=blue]
    > acceptable conversion).
    >
    > The "testA = FIRST_VALUE" seems to be fine. Is this a VC++ 6.0 quirk or[/color]
    am I doing something wrong? Why won't B[color=blue]
    > inherit the overloaded operator?[/color]

    Because the B::operator=(co nst B&), which is _implicit_ and provided
    by the compiler for you, _hides_ all others.

    Victor


    Comment

    • Andy Jarrell

      #3
      Re: Inheriting overloaded operators


      "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<YTNsb.193 609$e01.709899@ attbi_s02>...[color=blue]
      > "Andy Jarrell" <andyj@dacaudio .com> wrote...[color=green]
      > > I'm trying to inherit from a specific class that has an overloaded[/color]
      > operator. The problem I'm getting is that certain[color=green]
      > > overloaded operators don't seem to come with the inheritance. For[/color]
      > example:[color=green]
      > >
      > > // TestA.h ---------------------------------------
      > >
      > > #include <iostream>
      > >
      > > enum Aval
      > > {
      > > FIRST_VALUE,
      > > SECOND_VALUE,
      > > THIRD_VALUE
      > > };
      > >
      > > class A
      > > {
      > > private:
      > > Aval value;
      > >
      > > public:
      > > A()
      > > {
      > > value = Aval(0);
      > > std::cout << "A() constructor" << std::endl;
      > > }
      > >
      > > A( Aval val ) : value(val)
      > > {
      > > std::cout << "A(val) constructor" << std::endl;
      > > }
      > > virtual ~A();
      > >
      > > virtual A & operator=( const A & otherError );
      > > virtual A & operator=( const Aval & otherValue );
      > >
      > > virtual Aval GetValue() { return value; }
      > > };
      > >
      > >
      > > // TestA.cpp --------------------------------------
      > >
      > > #include "TestA.h"
      > > #include <iostream>
      > >
      > > A::~A()
      > > {
      > > std::cout << "A destructed" << std::endl;
      > > }
      > >
      > > A & A::operator=( const A & otherError )
      > > {
      > > // Check for self-assignment
      > > if (this == &otherError)
      > > {
      > > return *this;
      > > }
      > >
      > > value = otherError.valu e;
      > > return *this;
      > > }
      > >
      > >
      > > A & A::operator=( const Aval & otherValue )
      > > {
      > > value = otherValue;
      > > return *this;
      > > }
      > >
      > > // Test B.h --------------------------------------
      > >
      > > #include "TestA.h"
      > > #include <iostream>
      > >
      > >
      > > class B : public A
      > > {
      > > public:
      > > B()
      > > {
      > > std::cout << "B() constructor" << std::endl;
      > > }
      > >
      > > virtual ~B()
      > > {
      > > std::cout << "B destructed" << std::endl;
      > > }
      > >
      > > };
      > >
      > >
      > > // main.cpp --------------------------------------
      > >
      > > int main( int argc, char* argv[] )
      > > {
      > > A testA;
      > > B testB;
      > >
      > > testA = FIRST_VALUE;
      > > testB = SECOND_VALUE;
      > >
      > > return 0;
      > > }
      > >
      > >
      > > When compiling this in VC++ 6.0, I get the error for the "testB =[/color]
      > SECOND_VALUE" line of code:[color=green]
      > >
      > > error C2679: binary '=' : no operator defined which takes a right-hand[/color]
      > operand of type 'enum Aval' (or there is no[color=green]
      > > acceptable conversion).
      > >
      > > The "testA = FIRST_VALUE" seems to be fine. Is this a VC++ 6.0 quirk or[/color]
      > am I doing something wrong? Why won't B[color=green]
      > > inherit the overloaded operator?[/color]
      >
      > Because the B::operator=(co nst B&), which is _implicit_ and provided
      > by the compiler for you, _hides_ all others.
      >
      > Victor
      >
      >[/color]

      So for all implicit operators I must specifically overload them. I.e.,

      class B : public A
      {
      public:
      virtual B & operator=( const B & otherError );
      virtual B & operator=( const Aval & otherValue );
      // yadda, yadda, . . .
      }

      And them implement them, calling the base class operator if I wish.

      But, the following compiles without a hitch:

      A testA1, testA2;
      B testB1, testB2;

      testA2 = testA1;
      testB1 = testB2;

      Is it that the implicit "=" operator is called for testB1, whereas the overloaded operator is called for testA1. I
      think I just answered my own question.

      Does the same hold true for implicit things like the copy constructor? How do I inherit operators from the base class?

      Thanks for your insight.

      Andy


      Comment

      • Victor Bazarov

        #4
        Re: Inheriting overloaded operators

        "Andy Jarrell" <andyj@dacaudio .com> wrote...[color=blue]
        > [...]
        > But, the following compiles without a hitch:
        >
        > A testA1, testA2;
        > B testB1, testB2;
        >
        > testA2 = testA1;
        > testB1 = testB2;
        >
        > Is it that the implicit "=" operator is called for testB1, whereas the[/color]
        overloaded operator is called for testA1. I[color=blue]
        > think I just answered my own question.[/color]

        You did.
        [color=blue]
        >
        > Does the same hold true for implicit things like the copy constructor?[/color]
        How do I inherit operators from the base class?

        Try delcaring them as used:

        class A {
        ...
        };

        class B : public A {
        ...
        using A::operator=; // adds this name to this scope
        };

        Victor



        Comment

        • Andy Jarrell

          #5
          Re: Inheriting overloaded operators


          "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:ClRsb.1951 28$e01.712657@a ttbi_s02...[color=blue]
          > "Andy Jarrell" <andyj@dacaudio .com> wrote...[color=green]
          > > [...]
          > > But, the following compiles without a hitch:
          > >
          > > A testA1, testA2;
          > > B testB1, testB2;
          > >
          > > testA2 = testA1;
          > > testB1 = testB2;
          > >
          > > Is it that the implicit "=" operator is called for testB1, whereas the[/color]
          > overloaded operator is called for testA1. I[color=green]
          > > think I just answered my own question.[/color]
          >
          > You did.
          >[color=green]
          > >
          > > Does the same hold true for implicit things like the copy constructor?[/color]
          > How do I inherit operators from the base class?
          >
          > Try delcaring them as used:
          >
          > class A {
          > ...
          > };
          >
          > class B : public A {
          > ...
          > using A::operator=; // adds this name to this scope
          > };
          >
          > Victor
          >
          >
          >[/color]
          To answer my own question (yet again), the assignment operator is not inherited for understandable reasons as most
          derived classes have additional data members for which the base class assignment operator would not work. For those
          instances where the base class assignment operator I tried your suggestion:
          using A::operator=;
          in the class definition. The other method was to just rewrite the operator and axplicitly call the base operator by
          doing something like:
          virtual B & operator=( const B& other )
          {
          A::operator=( otherValue );
          return *this;
          }

          This works for the basic class assignment. Thanks for the insight. I also came across another post you made (God bless
          Google Groups) directing some users to items 15/16 in Scott Meyers Effective C++. I reread my copy and it helped clear
          things up.

          I've narrowed the problem I was experiencing down to this:

          class A
          {
          private:
          int data;
          public:
          virtual A & operator=( const int value );
          }

          class B : public A
          {
          public:
          virtual B & operator=( const int value );
          }

          The problem is that I'm now getting the error:
          'B::=' : overriding virtual function differs from 'A::=' only by return type or calling convention

          I understand that differing return types are not permissible ways of overloading. But, it seems to me that this is the
          basic function overloading. I mean, the function could just as much have been:

          class A
          {
          virtual A & foo(int a);
          }

          class B : public A
          {
          virtual B & foo(int b);
          }

          The above example would work. But the problem was that I was declaring the operators virtual, which probably confused
          the heck out of the compiler. Anyway, by changing them to:

          class A
          {
          private:
          int data;
          public:
          A & operator=( const int value );
          }

          class B : public A
          {
          public:
          B & operator=( const int value )
          {
          A::operator=( otherError );
          return *this;
          }
          }

          It worked. Working of Scott Meyers syntax I could also have done:
          static_cast<A&> (*this) = value;
          return *this;

          Thought I'd post this for posterity.

          Andy


          Comment

          • Victor Bazarov

            #6
            Re: Inheriting overloaded operators

            "Andy Jarrell" <andyj@dacaudio .com> wrote...[color=blue]
            >
            > "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message[/color]
            news:ClRsb.1951 28$e01.712657@a ttbi_s02...[color=blue][color=green]
            > > "Andy Jarrell" <andyj@dacaudio .com> wrote...[color=darkred]
            > > > [...]
            > > > But, the following compiles without a hitch:
            > > >
            > > > A testA1, testA2;
            > > > B testB1, testB2;
            > > >
            > > > testA2 = testA1;
            > > > testB1 = testB2;
            > > >
            > > > Is it that the implicit "=" operator is called for testB1, whereas the[/color]
            > > overloaded operator is called for testA1. I[color=darkred]
            > > > think I just answered my own question.[/color]
            > >
            > > You did.
            > >[color=darkred]
            > > >
            > > > Does the same hold true for implicit things like the copy constructor?[/color]
            > > How do I inherit operators from the base class?
            > >
            > > Try delcaring them as used:
            > >
            > > class A {
            > > ...
            > > };
            > >
            > > class B : public A {
            > > ...
            > > using A::operator=; // adds this name to this scope
            > > };
            > >
            > > Victor
            > >
            > >
            > >[/color]
            > To answer my own question (yet again), the assignment operator is not[/color]
            inherited for understandable reasons as most[color=blue]
            > derived classes have additional data members for which the base class[/color]
            assignment operator would not work. For those[color=blue]
            > instances where the base class assignment operator I tried your[/color]
            suggestion:[color=blue]
            > using A::operator=;
            > in the class definition. The other method was to just rewrite the operator[/color]
            and axplicitly call the base operator by[color=blue]
            > doing something like:
            > virtual B & operator=( const B& other )
            > {
            > A::operator=( otherValue );
            > return *this;
            > }
            >
            > This works for the basic class assignment. Thanks for the insight. I[/color]
            also came across another post you made (God bless[color=blue]
            > Google Groups) directing some users to items 15/16 in Scott Meyers[/color]
            Effective C++. I reread my copy and it helped clear[color=blue]
            > things up.
            >
            > I've narrowed the problem I was experiencing down to this:
            >
            > class A
            > {
            > private:
            > int data;
            > public:
            > virtual A & operator=( const int value );
            > }
            >
            > class B : public A
            > {
            > public:
            > virtual B & operator=( const int value );
            > }
            >
            > The problem is that I'm now getting the error:
            > 'B::=' : overriding virtual function differs from 'A::=' only by return[/color]
            type or calling convention

            There should be no such warning because the two functions have
            _covariant_ return types. It is expressly permitted by the Standard.
            Your compiler is likely out of date in that regard.
            [color=blue]
            >
            > I understand that differing return types are not permissible ways of[/color]
            overloading. But, it seems to me that this is the[color=blue]
            > basic function overloading. I mean, the function could just as much have[/color]
            been:[color=blue]
            >
            > class A
            > {
            > virtual A & foo(int a);
            > }
            >
            > class B : public A
            > {
            > virtual B & foo(int b);
            > }
            >
            > The above example would work. But the problem was that I was declaring[/color]
            the operators virtual, which probably confused[color=blue]
            > the heck out of the compiler.[/color]

            No. There is no _overloading_ based on return value types. It is
            a common confusion point, so don't worry.

            _Overloading_ only concerns _argument_ number,types, and order.
            [color=blue]
            > Anyway, by changing them to:
            >
            > class A
            > {
            > private:
            > int data;
            > public:
            > A & operator=( const int value );
            > }
            >
            > class B : public A
            > {
            > public:
            > B & operator=( const int value )
            > {
            > A::operator=( otherError );
            > return *this;
            > }
            > }
            >
            > It worked. Working of Scott Meyers syntax I could also have done:
            > static_cast<A&> (*this) = value;
            > return *this;
            >
            > Thought I'd post this for posterity.[/color]

            Good idea.

            Victor


            Comment

            Working...