overloading operator of inherated classes

Hi all,

I have a class A, from which three classes Aa Ab and Ac are inherated.
In class A I have defined some functions by virtual foo()=0, which I implemented in each subclass. Each class is written in a seperated .h and .cpp file.

However, now I think it is possible to overload the operator+ INSIDE each class (including pure virtual in class A), such that something like

1
2
3
4
5
int main()
{
A *value = new Aa();
A value2 = *value + 1.0f;
}


This should be realizable, because the operator+ is part of the Aa class. Now, I would like to do something like

1
2
3
4
5
int main()
{
A *value = new Aa();
A value2 = 1.0f + *value;
}


This time, I expect I cannot overwrite the operator+, because it is not part of either class A or class Aa.

What can I do?

Thank you,
curator
Define a non-member operator+ which forwards to the member operator+=, which is how it's normally done anyway.

A more important question: what do you expect your operator+ to return? If you return a value of type A (as you seem to do in your sample code), you're going to lose all the non-A members of Aa. If you plan to return a reference, then it should be operator+= anyway, to preserve semantics.
Interesting point. That might be a problem. Maybe I have to tell a few words about the overall plan. In my program, I would like to the capable of handling three data structures. The have some information in common (stored in class A) and in additon each structure was its own information (class Aa etc.). So, if i loose this information, this would be bad. My idea was to have one code for the complete program and use class A everywhere. Only when I start the programs main function, I decide wheater I work with class Aa or Ab etc., which might be depending on use input. So, I plan something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
A getValue()
{
      Aa s;
      Ab t:
      if(random)
           return s;
      else
          return t;
}

int main()
{
     A value = getValue();
     A value2 = 1.0f + A // here use different functions, wheater A is Aa od Ab
     value2.printf() // here use different functions, wheater A is Aa od Ab
}


Maybe my complete idea is corrupt. Then it was good to ask, but what is the solutation?
As long as you're dealing with objects (rather than references to them, or, possibly wrapped, pointers), you don't get runtime polymoprhism: your getValue() returns an A, never Aa or Ab. Your value and value2 are instances of A, not Aa or Ab. Your call to value2.printf() calls the member of A because that's value2's most derived type.

On a larger scale, "information in common" is not a reason to use inheritance, it's a has-a relationship, although your sample code shows common behavior (addition to float and member function print), which is more plausible. Give more details.
The canonical technique to combine value semantics with run-time polymorphism is to access the objects indirectly via a surrogate. The surrogate collapses an entire hierarchy into a single value type.

Trivially (without clone):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <memory>
#include <iostream>

struct base
{
    using ptr = std::shared_ptr<base> ;

    base( int i ) : a(i) {}
    virtual ~base() {}

    virtual ptr plus( int i ) const { return std::make_shared<base>( a+i ) ; }

    virtual  std::ostream& print( std::ostream& stm ) const
    { return stm << "base{" << a << '}' ; }

    int a ;
};

struct derived : base
{
    derived( int i, int j ) : base(i), b(j) {}

    virtual  ptr plus( int i ) const override
    { return std::make_shared<derived>( a+i, b+i ) ; }

    virtual  std::ostream& print( std::ostream& stm ) const
    { return stm << "derived{" << a << ',' << b << '}' ; }

    int b ;
};

struct surrogate
{
    // in real life, we may need to colour constructors
    surrogate( int i ) : p( std::make_shared<base>(i) ) {}
    surrogate( int i, int j ) : p( std::make_shared<derived>(i,j) ) {}

    surrogate( base::ptr pp ) : p(pp) {}

    base::ptr p ;
};

surrogate operator+ ( const surrogate& s, int i ) { return s.p->plus(i) ; }
surrogate operator+ ( int i, const surrogate& s ) { return s + i ; }
std::ostream& operator<< ( std::ostream& stm, const surrogate& s )
{ return s.p->print(stm) ; }

int main()
{
    surrogate a(100), b(200,300) ;
    std::cout << "a: " << a << "  a+1234: " << a+1234 << '\n' ;
    std::cout << "b: " << b << "  5678+b: " << 5678+b << '\n' ;
}


http://ideone.com/03mN3B
Ok, lets give them a some example names. Lets say "A" is vehicle, and "Aa" is a car, "Ab" a bicicle. Both have a std::vector<wheels> in common, but furthermore each object has different values.

Now, my main program "constructs" a vehicle, lets say

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
vehicle *getValue()
{
      if(random)
           return new car();
      else
          return new bicicle();
}
void construct (vehicle *in)
{
          in->add(wheel);
          in->add(wheel);
}

int main()
{
        vehicle *my = getValue();
        construct(my);
        bool vehicle_complete = my->IsComplete(); //true for bicicle, but false for car
}

class vehicle
{
public: 
inline void addWheel(){wheels++;};
virtual bool IsComplete()=0;

protected:
int wheels;
}

class car:public vehicle
{
public: 
bool IsComplete(){return wheels>=4};
}

class bicicle:public vehicle
{
public: 
bool IsComplete(){return wheels>=2};
}


So, this time I only use references. Does this make my problem more clear?
Those aren't references. Anyway, It only makes it more certain that implementing it with my = 2 + my; would be wrong: you don't clone a vehicle on a conveyor belt when you need to add two more wheels and junk the old one! You just bolt on those wheels to the vehicle you already have, with no copying. That's my += 2; (if you care to build a surrogate or some similar class - I would call it VehicleOnConveyor, since it isn't a Vehicle until you can .drive() it). Or just call a member function: my->attachAxle(); -- that's more clear, the reader won't have to try to guess two of what you're adding (wheels? seats? subwoofers?)
Last edited on
Thank you for your patience. Ok, lets say a car has subwoofers (which the bicicle doesnt have) and the bicicle has spokes (which the car doent have). Lets say all values have some kind of level, which can be upgraded.
So what i want to do is (something like)
 
newVehicle *a =&(2 + *oldvehicle);


So, I really want to copy, store it in a pointer to the base class vehicle (but keeping the bicicle or car class). The oldvehicle should NOT be upgraded. By the operator+, i want to upgrade all wheels (higher radius) and maybe more stable spokes or subwoofers, depneding on class.

I know thats just an example, and as every example, it is only a part of the problem. The real project is by far more complicated.
Topic archived. No new replies allowed.