operator=

C

Corey Cooper

I have a class for which I needed to create an operator= function. I then
use that as a base class for another class, which also needs an operator=.
What is the syntax to use in the derived class operator= function to copy
the base classes variables in the derived class (without just copying the
code?)

A much simplified example:

class Base
{
public:
Base();
~Base();

Base &operator=(const Base &B);

protected:
int i;
}

Base &Base::eek:perator=(const Base &B)
{
if (this == &B)
return *this;
i = B.i;
return *this;
};


class Derived : public Base
{
Derived();
~Derived();

Derived &operator=(const Derived &D);

protected:
int n;
};

Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)
return *this;

// None of these work!
//(Base)(*this) = ::eek:perator=B;
//(*this) =(const Base &)B;

n = B.n;
return *this;
};

And yet, in code not directly in these classes, this works fine:
Base b;
Derived d;
d = b;

Thanks!
Corey
 
C

cipher

Hi,

make method "operator=" virtual, this should help. Non-virtual methods
cannot be overwritten, so you will always use operator= from class
Base.

Greetings from Bavaria,


Markus
 
S

sheffmail

I have a class for which I needed to create an operator= function. I then
use that as a base class for another class, which also needs an operator=.
What is the syntax to use in the derived class operator= function to copy
the base classes variables in the derived class (without just copying the
code?)

A much simplified example:

class Base
{
public:
Base();
~Base();

Base &operator=(const Base &B);

protected:
int i;

}

Base &Base::eek:perator=(const Base &B)
{
if (this == &B)
return *this;
i = B.i;
return *this;

};

class Derived : public Base
{
Derived();
~Derived();

Derived &operator=(const Derived &D);

protected:
int n;

};

Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)
return *this;

// None of these work!
//(Base)(*this) = ::eek:perator=B;
//(*this) =(const Base &)B;

n = B.n;
return *this;

};

And yet, in code not directly in these classes, this works fine:
Base b;
Derived d;
d = b;

Thanks!
Corey

Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)
return *this;

// None of these work!
//(Base)(*this) = ::eek:perator=B;
//(*this) =(const Base &)B;

n = B.n;
Base::eek:perator =(B);

return *this;
};
 
J

jason.cipriani

I have a class for which I needed to create an operator= function. I then
use that as a base class for another class, which also needs an operator=.
What is the syntax to use in the derived class operator= function to copy
the base classes variables in the derived class (without just copying the
code?)
Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)
return *this;

You want:

Base::eek:perator = (B);
n = B.n;
return *this;

};


That's also the general syntax for calling the base implementation of
a function.

class Base {
virtual void f () { }
};

class Derived : public Base {
void f () {
Base::f();
// ...
}
};


Jason
 
J

jason.cipriani

make method "operator=" virtual, this should help. Non-virtual methods
cannot be overwritten, so you will always use operator= from class
Base.

That will not help the main problem, though. Also, the derived
operator = takes a Derived&, not a Base&. Virtual or not, if you are
calling operator = on a Base, it will always use the Base one, e.g.:

void assign (Base &a, const Base &b) {
a = b;
}

Will always call Base::eek:perator= only, no matter what derived classes
you pass it. Making operator = virtual in the Base will case
Derived::eek:perator= to be called only if there is a
Derived::eek:perator=(Base&), e.g.:


class Base {
public:
virtual Base & operator = (const Base &); // (1)
};

class Derived {
public:
Derived & operator = (const Derived &); // (2)
Derived & operator = (const Base &); // (3)
};

void assign (Base &a, const Base &b) {
a = b;
}

void f () {
Derived a, b;
a = b; // This calls (2).
assign(a, b); // This calls (3).
}


And assign(a, b) would call (1) if (1) wasn't virtual. But it will
never call (2).


Jason
 
C

Corey Cooper

You want:
Base::eek:perator = (B);



That's also the general syntax for calling the base implementation of
a function.

Ahh! I forgot that operator= is like any other function, and I kept wanting
to put something on the left of the equals sign!

Thanks All!
 
J

James Kanze

I have a class for which I needed to create an operator=
function. I then use that as a base class for another class,
which also needs an operator=. What is the syntax to use in
the derived class operator= function to copy the base classes
variables in the derived class (without just copying the
code?)
A much simplified example:
class Base
{
public:
Base();
~Base();
Base &operator=(const Base &B);
protected:
int i;
}
Base &Base::eek:perator=(const Base &B)
{
if (this == &B)

What's this check for? It just wastes time, and is usually a
sign of other problems (but here, it's just unnecessary).
return *this;
i = B.i;
return *this;
};
class Derived : public Base
{
Derived();
~Derived();
Derived &operator=(const Derived &D);
protected:
int n;
};
Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)

(As above.)
return *this;
// None of these work!
//(Base)(*this) = ::eek:perator=B;
//(*this) =(const Base &)B;

What's wrong with just:

Base::eek:perator=( B ) ;
n = B.n;
return *this;
};
And yet, in code not directly in these classes, this works fine:
Base b;
Derived d;
d = b;

It does? It shouldn't compile.
 
C

Corey Cooper

I have a class for which I needed to create an operator=
function. I then use that as a base class for another class,
which also needs an operator=. What is the syntax to use in
the derived class operator= function to copy the base classes
variables in the derived class (without just copying the
code?)
A much simplified example:
class Base
{
public:
Base();
~Base();
Base &operator=(const Base &B);
protected:
int i;
}
Base &Base::eek:perator=(const Base &B)
{
if (this == &B)

What's this check for? It just wastes time, and is usually a
sign of other problems (but here, it's just unnecessary).
return *this;
i = B.i;
return *this;
};
class Derived : public Base
{
Derived();
~Derived();
Derived &operator=(const Derived &D);
protected:
int n;
};
Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)

(As above.)
return *this;
// None of these work!
//(Base)(*this) = ::eek:perator=B;
//(*this) =(const Base &)B;

What's wrong with just:

Base::eek:perator=( B ) ;
n = B.n;
return *this;
};
It does? It shouldn't compile.

VC++ 6.0 it works.
c.
 
J

James Kanze

[...]
VC++ 6.0 it works.

I don't see how. VC++ 6.0 is very old and outdated, but even
then, I don't see what assignment operator it could possibly
use. Are you sure you don't have the assignment backwards:
b = d ;
should work.
 
J

James Kanze

That sounds like a very bad idea.
void fn(Base& b, Derived& d)
{
b = d;
d = b;
}
AFAIK, in both of the above, Base::eek:p=(const Base&) will be
called, but what if 'b' is a reference to a Derived object?

As far as I can see, "d = b" is illegal. There is no operator=
in Derived which can be called with a Base.
I don't think the base class should have an op= function. I
think the right thing to do is to make the Base::eek:p= private
and not implemented.

In general, assignment and polymorphism don't work well
together, and in general, assignment should be banned in
polymorphic classes. But the original poster didn't say why he
was deriving; if the motive isn't polymorphism, then it's
possible that providing assignment in both would be justified.
 
L

Lionel B

In general, assignment and polymorphism don't work well together, and in
general, assignment should be banned in polymorphic classes.

That's a bit strong, isn't it? Ok, I don't want to assign an apple to a
pear, even if they're both fruit; but might I at least be allowed to
assign an apple to an apple?
 
L

LR

Corey said:
I have a class for which I needed to create an operator= function. I then
use that as a base class for another class, which also needs an operator=.
What is the syntax to use in the derived class operator= function to copy
the base classes variables in the derived class (without just copying the
code?)

A much simplified example:

class Base
{
public:
Base();
~Base();

Base &operator=(const Base &B);

protected:
int i;
}
;


Base &Base::eek:perator=(const Base &B)
{
if (this == &B)
return *this;
i = B.i;
return *this;
};


class Derived : public Base
{
Derived();
~Derived();

Derived &operator=(const Derived &D);

protected:
int n;
};

Derived &Derived::eek:perator=(const Derived &B)
{
if (this == &B)
return *this;

// None of these work!
//(Base)(*this) = ::eek:perator=B;
//(*this) =(const Base &)B;

n = B.n;
return *this;
};

And yet, in code not directly in these classes, this works fine:
Base b;
Derived d;
d = b;

I don't see how. Derived's default ctor is private above. I suspect
that you didn't cut and paste when you posted. It adds a little bit of
confusion.

I also think that assigning a base instance to a derived instance is
rather ugly. Can be done, but I'm curious as to why you want to.
Perhaps better IMHO to create a ctor for the derived class like
Derived(const Base &b, const int v) : Base(b), n(v) {}

Please consider the following code, and also, please see
http://www.gotw.ca/gotw/059.htm


NB, I've assumed that you did in fact want Derived(), ~Derived() and
Derived &operator=(const Derived &d) to be public.

class Base
{
static int testValue() { return -99; }
public:
void swap(Base &b) {
std::swap(b.i,i);
}
Base() : i(testValue()) {}
Base(const int v) : i(v) {} // just for testing
Base(const Base &b) : i(b.i) {}
virtual ~Base() {} // virtual

Base &operator=(const Base &B);

protected:
int i;
};

Base &Base::eek:perator=(const Base &b)
{
Base temp(b);
swap(temp);
return *this;
}


class Derived : public Base
{
static int testValueA() { return -55; }
static int testValueB() { return -52; }
public: // So the code you provided to exercise these can compile
void swap(Derived &d) {
Base::swap(d);
std::swap(d.n,n);
}
Derived() : Base(), n(testValueA()) {}
Derived(const Derived &d) : Base(d), n(d.n) {}

Derived(const Base &b, const int v) : Base(b), n(v) {}

// a ctor like this might not be the best thing to do.
Derived(const Base &b) : Base(b), n(testValueB()) {}
~Derived() {}

Derived &operator=(const Derived &d);
Derived &operator=(const Base &b);

protected:
int n;
};

Derived &Derived::eek:perator=(const Derived &d)
{
Derived temp(d);
swap(temp);
return *this;
}


Derived &Derived::eek:perator=(const Base &b) {
// This seems rather ugly to me.
// NB that we're not preserving
// what's on the left hand side of the =
// we use to call this.
// We could play games to do that
// if that's what you want, but I tend to think
// that you'd be better off using some other syntax
// for that.
Derived temp(b);
swap(temp);
return *this;
}

int main() {
Base b(44); // changed for testing
Derived d;
d = b; // Why? What?
d = Derived(b,67); // might be better IMHO
}

I'm not clear on what you want to do. I think that someone reading your
code, maybe even you, might have to pause over d=b; What does that do?

If you want d=b to result in a change to d.i but not d.n then perhaps
you ought to consider a ctor like,

Derived(const Base &b, const Derived &d) : Base(b), n(d.n) {}

and then write
d = Derived(b,d);

which I think will communicate your intent a little better than an
unusual Derived &operator=(const Base &) ever could. IMO.

But this sort of stuff doesn't seem pretty to me, so I'd like to know,
why do you want to do this?

LR
 
F

Frank Birbacher

Hi!

James said:
As far as I can see, "d = b" is illegal. There is no operator=
in Derived which can be called with a Base.

Only because the derived operator = hides the one of the base class.
This is a good thing because it makes "d = b" fail.
In general, assignment and polymorphism don't work well
together, and in general, assignment should be banned in
polymorphic classes. But the original poster didn't say why he
was deriving; if the motive isn't polymorphism, then it's
possible that providing assignment in both would be justified.

In which case the op = could safely be protected and be called from
derived classes.

Frank
 
J

James Kanze

That's a bit strong, isn't it? Ok, I don't want to assign an
apple to a pear, even if they're both fruit; but might I at
least be allowed to assign an apple to an apple?

In which case, presumably, the client code will be dealing with
apples, there's no polymorphism, and no problem. There's no
fundamental problem with providing assignment in the most
derived class, but there's usually also no real use for it,
since the whole point of having a hierarchy is that the client
code deals only with pointers and references to the base class.
 
J

James Kanze

James Kanze schrieb:
Only because the derived operator = hides the one of the base
class. This is a good thing because it makes "d = b" fail.

Yes. I hadn't actually thought about this aspect: hiding seems
natural for me for other reasons. But you're right that it
helps avoid this problem as well.

Of course, the derived class could provide an assignment
operator which worked with a Base const&. There are even a
(very) few special cases where this makes sense, but it's not
something you'd generally want to do.
In which case the op = could safely be protected and be called
from derived classes.

For example. Typically, however, the base class will have made
it private, without an implementation, in order to avoid it
accidentally being used, so you're sort of stuck. (Of course,
most base classes won't have any data anyway, at least when
inheritance is being used for polymorphism, so you don't need to
call it's assignment operator in the derived class.)
 

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

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top