Does Virtual functionality works with assignment operator?


S

sukhpal

Hi
i have tried this following Example.
i am expecting the out-put as:
"in a my_first class assignment" but i am getting the out-put as
"in a base class assignment"

#include "iostream"
class my_abstract {
int a;
public:
virtual void operator =(my_abstract &s)
{
std::cout<< "in a base class assignment";

}
virtual void display() = 0 ;
};

class my_first : public my_abstract {
int b;
public:
virtual void operator =(my_first &s)
{
std::cout<< "in a my_first class assignment";
}
virtual void display() {
std::cout << "my_first";
}
};

class second_first : public my_abstract {
int b;
public:
virtual void operator =(second_first &s)
{
std::cout<< "in a second_first class assignment";
}
virtual void display() {
std::cout << "second_first";
}
};

void my_display(my_abstract &obj, my_abstract &obj1)
{
obj = obj1;
}
void main()
{
my_abstract *b;
b = new my_first;
my_abstract *b1;
b1 = new my_first;
my_display(*b, *b1);
}
 
Ad

Advertisements

I

Ian Collins

sukhpal said:
Hi
i have tried this following Example.
i am expecting the out-put as:
"in a my_first class assignment" but i am getting the out-put as
"in a base class assignment"
That's correct, you can't have a virtual assignment operator.
 
K

Kai-Uwe Bux

To answer the question
Does Virtual functionality works with assignment operator?

from the subject line: yes (however, this is in my experience more or less
useless).

sukhpal wrote:
Hi
i have tried this following Example.
i am expecting the out-put as:
"in a my_first class assignment" but i am getting the out-put as
"in a base class assignment"

#include "iostream"
class my_abstract {
int a;
public:
virtual void operator =(my_abstract &s)
{
std::cout<< "in a base class assignment";

}
virtual void display() = 0 ;
};

class my_first : public my_abstract {
int b;
public:
virtual void operator =(my_first &s)
{
std::cout<< "in a my_first class assignment";
}
virtual void display() {
std::cout << "my_first";
}
}; [snip]
void my_display(my_abstract &obj, my_abstract &obj1)
{
obj = obj1;
}
void main()
{
my_abstract *b;
b = new my_first;
my_abstract *b1;
b1 = new my_first;
my_display(*b, *b1);
}

The assignment operator in my_first does not override the assignment from
the base class since the signatures do not match. The following simplified
program shows the phenomenon:

struct Base {

virtual
char const * func ( Base & ) {
return "base";
}

};

struct Derived : public Base {

virtual
char const * func ( Derived & ) {
return ( "derived" );
}

};

char const * display ( Base & l, Base & r ) {
return ( l.func( r ) );
}

#include <iostream>
#include <ostream>

#define PRINT( expr ) std::cout << #expr << " : " << expr << '\n'

int main ( void ) {
Base b;
Derived d;
PRINT( b.func( b ) );
PRINT( b.func( d ) );
PRINT( d.func( d ) );
PRINT( display( b, b ) );
PRINT( display( b, d ) );
PRINT( display( d, b ) );
PRINT( display( d, d ) );
}


Expected output:
b.func( b ) : base
b.func( d ) : base
d.func( d ) : derived
display( b, b ) : base
display( b, d ) : base
display( d, b ) : base
display( d, d ) : base

Note that display(d,d) differs from d.func(d).

The following change is a remedy:

struct Base {

virtual
char const * func ( Base & ) {
return "base";
}

};

struct Derived : public Base {

virtual
char const * func ( Base & ) {
return ( "derived" );
}

};

char const * display ( Base & l, Base & r ) {
return ( l.func( r ) );
}

#include <iostream>
#include <ostream>

#define PRINT( expr ) std::cout << #expr << " : " << expr << '\n'

int main ( void ) {
Base b;
Derived d;
PRINT( b.func( b ) );
PRINT( b.func( d ) );
PRINT( d.func( d ) );
PRINT( display( b, b ) );
PRINT( display( b, d ) );
PRINT( display( d, b ) );
PRINT( display( d, d ) );
}

Expected output:
b.func( b ) : base
b.func( d ) : base
d.func( d ) : derived
display( b, b ) : base
display( b, d ) : base
display( d, b ) : derived
display( d, d ) : derived



BTW: Now one can understand that for a virtual assignment operator my_first
would need an operator= that takes a my_abstract (const) & as its argument.
Since assignment across different types is usually not possible, such an
assignment operator is by and large useless.



Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Ian said:
That's correct, you can't have a virtual assignment operator.

Well, it appears that you can, but it is useless:

#include <iostream>
#include <ostream>

struct Base {

virtual
void operator= ( Base const & ) {
std::cout << "base\n";
}

};

struct Derived : public Base {

virtual
void operator= ( Base const & ) {
std::cout << "derived\n";
}

};

void display ( Base & lhs, Base & rhs ) {
lhs = rhs;
}

int main ( void ) {
Base b;
Derived d;
b = b;
b = d;
d = b;
d = d;
display( b, b );
display( b, d );
display( d, b );
display( d, d );
}

Output:
base
base
derived
base
base
base
derived
derived

The most funny thing is line 4 where d=d prints "base", which I do not
understand. Is there undefined behavior? Standard anyone?


Best

Kai-Uwe Bux
 
G

Greg Herlihy

Ian Collins wrote:

Well, it appears that you can, but it is useless:

#include <iostream>
#include <ostream>

struct Base {

  virtual
  void operator= ( Base const & ) {
    std::cout << "base\n";
  }

};

struct Derived : public Base {

  virtual
  void operator= ( Base const & ) {
    std::cout << "derived\n";
  }

};

void display ( Base & lhs, Base & rhs ) {
  lhs =  rhs;

}

int main ( void ) {
  Base b;
  Derived d;
  b = b;
  b = d;
  d = b;
  d = d;
  display( b, b );
  display( b, d );
  display( d, b );
  display( d, d );

}

Output:
base
base
derived
base
base
base
derived
derived

The most funny thing is line 4 where d=d prints "base", which I do not
understand. Is there undefined behavior? Standard anyone?

No, there is no undefined behavior in the above program. The
assignment, d=d, calls Derived's implicit copy assignment function
(because the program has not defined one explicitly). The implicit
copy assignment operator performs a memberwise copy of the object's
subobjects. Since Base is a subobject of Derived, Base's copy
assignment function (which is defined) is called to copy d's Base
object subobject.

Greg
 
Ad

Advertisements

J

James Kanze

Well, it appears that you can, but it is useless:

Of course you can. It's not useless, but it's usually a design
error.
#include <iostream>
#include <ostream>
struct Base {
virtual
void operator= ( Base const & ) {
std::cout << "base\n";
}
};
struct Derived : public Base {
virtual
void operator= ( Base const & ) {

Note that this is an overload. It is NOT a copy assignment
operator, so the compiler will still generate its version of a
copy assignment operator (which will call the copy assignment
operator you defined in the base class).
std::cout << "derived\n";
}
};
void display ( Base & lhs, Base & rhs ) {
lhs = rhs;
}
int main ( void ) {
Base b;
Derived d;
b = b;
b = d;
d = b;
d = d;
display( b, b );
display( b, d );
display( d, b );
display( d, d );
}

The most funny thing is line 4 where d=d prints "base", which
I do not understand.

The compiler has generated a copy assignment operator for
Derived. It's the best match here, so it's what gets called.
And it calls the base class assignment operator, which does the
output.

Note that in anything but a toy example like this, the results
probably wouldn't make sense. If I do something like: a = b, I
expect that a and b are "equivalent" in some sense after the
operation. In most cases, that equivalence should mean that
they have the same type. And there's no way you can implement
that. (In other words, there's a very real reason why "OO"
languages don't support value semantics.)
Is there undefined behavior? Standard anyone?

No undefined behavior. See §12.8, and the conditions controling
when and how the compiler generates a copy assignment operator.
(Then overload resolution, but I think that once you realize
that Derived has two assignment operators, the rest will be
clear to you.)
 
Ad

Advertisements


Top