Inheriting overloaded operators

A

Andy Jarrell

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::eek:perator=( const A & otherError )
{
// Check for self-assignment
if (this == &otherError)
{
return *this;
}

value = otherError.value;
return *this;
}


A & A::eek:perator=( 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.
 
V

Victor Bazarov

Andy Jarrell said:
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::eek:perator=( const A & otherError )
{
// Check for self-assignment
if (this == &otherError)
{
return *this;
}

value = otherError.value;
return *this;
}


A & A::eek:perator=( 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?

Because the B::eek:perator=(const B&), which is _implicit_ and provided
by the compiler for you, _hides_ all others.

Victor
 
A

Andy Jarrell

Victor Bazarov said:
Andy Jarrell said:
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::eek:perator=( const A & otherError )
{
// Check for self-assignment
if (this == &otherError)
{
return *this;
}

value = otherError.value;
return *this;
}


A & A::eek:perator=( 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?

Because the B::eek:perator=(const B&), which is _implicit_ and provided
by the compiler for you, _hides_ all others.

Victor

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
 
V

Victor Bazarov

Andy Jarrell said:
[...]
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.

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

Try delcaring them as used:

class A {
...
};

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

Victor
 
A

Andy Jarrell

Victor Bazarov said:
Andy Jarrell said:
[...]
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.

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

Try delcaring them as used:

class A {
...
};

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

Victor
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::eek:perator=;
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::eek:perator=( 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::eek:perator=( 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
 
V

Victor Bazarov

Andy Jarrell said:
Andy Jarrell said:
[...]
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.

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

Try delcaring them as used:

class A {
...
};

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

Victor
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::eek:perator=;
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::eek:perator=( 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

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.
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.

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.
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::eek:perator=( 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.

Good idea.

Victor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top