Avatar of jochemspek
jochemspek
Flag for Netherlands asked on

re-implementing virtual assignment operator of a templated class

Dear all,

I have an issue with re-implementing the assignment operator of
a base class, of which the derived class is templated.

the code:

#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <exception>

using namespace std;

class AbstractProperty {
public:
    virtual string getValue() = 0;
    virtual void setValue( string value ) = 0;
    virtual AbstractProperty & operator = ( AbstractProperty & rhs ) = 0;
};

template< class T >
class Property : public AbstractProperty {
public:
    Property( T value ):
        m_value( value ){
    }

    string getValue(){
        stringstream ss;
        ss << m_value;
        return( ss.str() );
    }
    void setValue( string value ){
        stringstream ss;
        ss << value;
        ss >> m_value;
    }
    AbstractProperty & operator = ( AbstractProperty & rhs ){
        try{
            Property & p = dynamic_cast<Property & >( rhs );
            this->m_value = p.m_value;
        }
        catch( exception & e ){
            cout << "eek ! a " << e.what( ) << endl;
        }
        return( * this );
    }

private:
    T m_value;
};

void main( void ){
    int i1 = 1;
    int i2 = 2;

    float f = 0.5;

    Property<int> Pi1( i1 );
    Property<int> Pi2( i2 );

    Property<float> Pf( f );

    Pi2.setValue( "3" );
    Pf.setValue( "0.25" );

    cout << "Pi1: " << Pi1.getValue() << endl;
    cout << "Pi2: " << Pi2.getValue() << endl;
    cout << "Pf: " << Pf.getValue() << endl;

    Pi1 = Pf; // works, but with a Bad Dynamic (as expected)
    Pi1 = Pi2; // doesn't compile, because
                //  unresolved external symbol "public: virtual class AbstractProperty
                // & __thiscall AbstractProperty::operator=(class AbstractProperty &)"

    cout << "Pi1: " << Pi1.getValue() << endl;

}

What I *really* don't understand, is why the two Property<int> instances
being assigned results in an unresolved function, shouldnt the two instances
compare as two Property<int> classes, and thus be implemented by the template ?
it's not a matter of the argument to the assignment operator not being constant,
Ive checked.

any input is appreciated,

Jonathan
Editors IDEsC++

Avatar of undefined
Last Comment
phoffric

8/22/2022 - Mon
ASKER CERTIFIED SOLUTION
evilrix

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
jochemspek

ASKER
@elvirix, thanks, but I still don't understand why the given code doesn't compile,
why doesnt the compiler resolve the assignment operator to be that of the Property<int> class ?

J
SOLUTION
evilrix

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
jochemspek

ASKER
ah. I think I got it, I'm confusing the situation where :

class A{
          virtual A & operator = ( A & a ) = 0;
};

class B : public A {
          virtual A & operator = ( A & a ){
               cout << " here ";
           }
}

B * b1 = new B();
B * b2 = new B();

* b1 = * b2;

in this situation, the assignment operator in B is called, even when
b1 and b2 are cast to A *..

J
evilrix

>> in this situation, the assignment operator in B is called

In function `B::operator=(B&)':
x.cpp:53: undefined reference to `A::operator=(A&)'
collect2: ld returned 1 exit status
make: *** [xprog] Error 1
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
SOLUTION
phoffric

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
jochemspek

ASKER
@evilrix:

sorry, that was from the top of my mind,
here's what i meant, which builds & runs..

class A{
public:
          virtual A & operator = ( A & a ) = 0;
};

class B : public A {
public:
          virtual A & operator = ( A & a ){
               B & b = static_cast< B & >( a );
               cout << " do something b'ish here ";
             return( * this );
           }
};

void main( void ){

      B * b1 = new B();
      B * b2 = new B();

      * ( A * )b1 = * ( A * )b2;
}

this works, but is it legal ?

@phoffric: thanks, how do you reckon does 2) relate to my example ?

J
SOLUTION
phoffric

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SOLUTION
evilrix

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
phoffric

@evilrix - LOL - What makes it heavier is that usually when something doesn't compile or build, the examples are there to show just that, and there are comments that indicate the problem. If I were just reading it and not trying the example stated, I would have thought that this would build. Maybe I'm doing something wrong. (I usually like to try out new things to help let it sink in. For some reason, I have never come across this item about trying to inherit the = operator. (Or maybe I saw it and thought "no problem".)
phoffric

@evilrix - does "just like me" apply to "a former member of the C++ standards council" as well as "a Brit"?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
evilrix

>> does "just like me" apply to "a former member of the C++ standards council" as well as "a Brit"?
Muhahaha -- I wish. No just the Brit part :)

The reason the example code doesn't build is because the function bodies are missing. You'll not thought that even with the function bodies in D it still would build unless you also implement them in B.
struct B {
        virtual int operator= (int); // { return 0; }
        virtual B& operator= (const B&); // { return *this; };
};
struct D : B {
   virtual int operator= (int) { return 0; }
        virtual D& operator= (const B&) { return *this; };
};
D dobj1;
D dobj2;
B* bptr = &dobj1;

void f() {
        bptr->operator=(99);    // calls D::operator=(int)
        *bptr = 99;             // ditto
        bptr->operator=(dobj2); // calls D::operator=(const B&)
        *bptr = dobj2;          // ditto
        dobj1 = dobj2;          // calls implicitly-declared
                                // D::operator=(const D&)
}
// I add main in order to build
int main()
{
}

Open in new window

phoffric

Ahh so! So that's how you work this C++ Language Spec thingy :)
I was so blind-sided by the question that I didn't even consider this intuitive, oh so clear, obvious answer (thanks to you).

Sorry jochemspek, I didn't mean to go off on a tangent that doesn't help you.