I'm having trouble getting the right operator to be accessed using polymorphism.
The code below is a simple representation of the problem, but it should get the point across.

//Horse.h

#ifndef HORSE_H_INCLUDED
#define HORSE_H_INCLUDED

#include <iostream>
#include <string>

class Horse
{
    public:
        Horse() {}
        Horse(int age) : itsAge(age) {}
        virtual ~Horse() {}

        virtual void operator=(const Horse& rHorse) {itsAge = rHorse.itsAge; std::cout<<"Horse operator= ..."<<std::endl;}

        int GetAge() const {return itsAge;}
        void SetAge(int age) {itsAge = age;}
        virtual std::string Speak() = 0;

    protected:
        int itsAge;
};

#endif // HORSE_H_INCLUDED
//Pony.h

#ifndef PONY_H_INCLUDED
#define PONY_H_INCLUDED

#include "Horse.h"

class Pony : public Horse
{
    public:
        Pony() {}
        Pony(int age) {itsAge = age;}
        ~Pony() {}

        void operator=(const Pony& pony) {itsAge = pony.itsAge;std::cout<<"Pony operator= ..."<<std::endl;}

        std::string Speak() {return "I'm a pony.";}
};

#endif // PONY_H_INCLUDED
//Main.cpp

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

using namespace std;

int main()
{
    Pony pony(10);
    Horse* pHorse = new Pony;
    *pHorse = pony;
    cout << pHorse->Speak() << endl << "It's age is " << pHorse->GetAge() << endl;
    delete pHorse;

    return 0;
}

Output of the program:

Horse operator= ...
I'm a pony.
It's age is 10

The problem being the first line in the output. The horse operator is called instead of the pony operator.
In this program, there's no difference. But in the application I'm working on, this is a problem since there's several classes, with different member variables.
I havn't really found a way to get around this other than defining a function virtual void Horse::operator=(const Pony&) which doesn't seem like a good solution.

Any ideas to have the right operator called are welcome!

Edited 7 Years Ago by BeyondTheEye: n/a

well with polymorphism you do need to use virtual functions in order for the program to know which functions to use. since it isn't virtual it is calling the horse operator=() function instead of the pony's operator=() function. there is a little more overhead with virtual function because of the v table implementation but that is one of the trade offs with polymorphism.

Its because you are not overriding the assignment operator. The virtual
function needs to have the same signature, for a derived class of that of
a ABC class or a base class.

Just replace your pony operator with this :

void operator=(const Horse& rHorse) {itsAge = rHorse.GetAge(); std::cout<<"Pony operator= ..."<<std::endl;}

Its because you are not overriding the assignment operator. The virtual
function needs to have the same signature, for a derived class of that of
a ABC class or a base class.

Just replace your pony operator with this :

void operator=(const Horse& rHorse) {itsAge = rHorse.GetAge(); std::cout<<"Pony operator= ..."<<std::endl;}

That would work in this case.
But the application I'm making has more complicated classes. These classes have different member variables than the base class, so it's impossible to change them using void operator=(const BaseClass&) .

Is there no other way than having several functions like:

virtual void BaseClass::operator=(class1&);
virtual void BaseClass::operator=(class2&);
// ...

It would make sense to declare the functions this way and override them in the child classes.
However, this would mean all classes have to be defined in one and them same header file (both the BaseClass and child class refer to one another)... Is there really no way to work around this?

you don't need to define each class in the same header file. all you need to do is include the header file from the base class into the child class header file. since you are use inclusion guarding you wont need to worry about multiply inclusions in you main.cpp file.

you don't need to define each class in the same header file. all you need to do is include the header file from the base class into the child class header file. since you are use inclusion guarding you wont need to worry about multiply inclusions in you main.cpp file.

Normally, yes. But suppose the following code:

//Horse.h
#ifndef HORSE_H_INCLUDED
#define HORSE_H_INCLUDED

class Horse
{
    public:
        Horse(int age) : itsAge(age) {}

        virtual void operator=(Horse& rHorse) {itsAge = rHorse.itsAge;}

    private:
        itsAge;
}

#endif // HORSE_H_INCLUDED
//Pony.h
#ifndef PONY_H_INCLUDED
#define PONY_H_INCLUDED

#include "Horse.h"

class Pony : public horse
{
    public:
        Pony(int age, int color) : itsColor(color) {itsAge = age;}

        //Error: Horse has no member named itsColor
        void operator=(Horse& rHorse) {itsAge = rHorse.itsAge; itsColor = rHorse.itsColor;}
        //Error: Horse has no virtual function with this signature. Thus, the operator will never be called using a Horse-pointer
        void operator=(Pony& rPony) {itsAge = rPony.itsAge; itsColor = rPony.itsColor;} 

    private:
        int itsColor;
}

#endif // PONY_H_INCLUDED

With the upper code I have no way of accessing Pony::itsColor from any operator. Only if I add another virtual function for Pony in the Horse class...

Edited 7 Years Ago by BeyondTheEye: n/a

try giving this a shot
horse.h

//Horse.h
#ifndef HORSE_H_INCLUDED
#define HORSE_H_INCLUDED

class Horse
{
    public:
        Horse(int age) : itsAge(age) {}

        virtual void operator=(Horse& rHorse) {itsAge = rHorse.itsAge;}

    private:
        itsAge;
}

#endif // HORSE_H_INCLUDED

pony.h

//Pony.h
#ifndef PONY_H_INCLUDED
#define PONY_H_INCLUDED

#include "Horse.h"

class Pony : public horse
{
    public:
        Pony(int age, int color) : itsColor(color) {itsAge = age;}
        virtual void operator=(Pony& rPony) {itsAge = rPony.itsAge; itsColor = rPony.itsColor;} 

    private:
        int itsColor;
}

#endif // PONY_H_INCLUDED

try giving this a shot
horse.h

//Horse.h
#ifndef HORSE_H_INCLUDED
#define HORSE_H_INCLUDED

class Horse
{
    public:
        Horse(int age) : itsAge(age) {}

        virtual void operator=(Horse& rHorse) {itsAge = rHorse.itsAge;}

    private:
        itsAge;
}

#endif // HORSE_H_INCLUDED

pony.h

//Pony.h
#ifndef PONY_H_INCLUDED
#define PONY_H_INCLUDED

#include "Horse.h"

class Pony : public horse
{
    public:
        Pony(int age, int color) : itsColor(color) {itsAge = age;}
        virtual void operator=(Pony& rPony) {itsAge = rPony.itsAge; itsColor = rPony.itsColor;} 

    private:
        int itsColor;
}

#endif // PONY_H_INCLUDED

No good.. The Pony::operator= will never be called using a Horse pointer. Even if the Pony object is assigned a color value.

This article has been dead for over six months. Start a new discussion instead.