Inheritance and copy constructors

J

jan247

Hi guys, thanks for taking time to read this..

Question 1
Let A be the superclass and B the subclass
A is not an abstract class.
print is a virtual function of A, which B implements.

A a = B;
a.print(); //this calls A's print function, but I want it to be B's
print. How do I implement this?

Question 2
Let A be the superclass and B the subclass
A overrides the + operator:

A A::eek:perator+(const A& right) const
{
...
}

but can I be able to get what subtype "right" is, and return an object
of the type of "right"?
 
V

Victor Bazarov

Hi guys, thanks for taking time to read this..

Question 1
Let A be the superclass and B the subclass
A is not an abstract class.
print is a virtual function of A, which B implements.

A a = B;
a.print(); //this calls A's print function, but I want it to be B's
print. How do I implement this?

Polymorphism only works with references or pointers.
Question 2
Let A be the superclass and B the subclass
A overrides the + operator:

A A::eek:perator+(const A& right) const
{
...
}

but can I be able to get what subtype "right" is, and return an object
of the type of "right"?

No. Operators that return values are not really indended to work
with polymorphism. You could try to fake it by returning a proxy
object which in turn contains a reference or a pointer to the real
object, but it's a PITA.

V
 
R

Rolf Magnus

Hi guys, thanks for taking time to read this..

Question 1
Let A be the superclass and B the subclass
A is not an abstract class.
print is a virtual function of A, which B implements.

A a = B;
a.print(); //this calls A's print function, but I want it to be B's
print. How do I implement this?

There is no way. You defined a as being of type A, and that's what it is. It
will be of that type throughout its entire lifetime.
Question 2
Let A be the superclass and B the subclass
A overrides the + operator:
Overrides?

A A::eek:perator+(const A& right) const
{
...
}

but can I be able to get what subtype "right" is, and return an object
of the type of "right"?

No.
 
J

Jens Theisen

A a = B;
a.print(); //this calls A's print function, but I want it to be B's
print. How do I implement this?

A const& a = B();

Note that when you write

A a = B();

this is most often not what you want: It's A's _copy_ ctor taking a copy
of B, probably losing information. This is called slicing and a common
surprise for people new to the language. You don't want a copy, you
want a polymorphic reference. You can choose from C-style pointer, C++
references and smart pointers (which encapsulate the former options in
convenient ways).
Question 2
Let A be the superclass and B the subclass
A overrides the + operator:

A A::eek:perator+(const A& right) const
{
...
}

but can I be able to get what subtype "right" is, and return an object
of the type of "right"?

See the other postings, but also note that there of course ways of
doing what you want to do.

Since polymorphism only works on pointers and references, you'll first
try to return and pass those. However, in the case of returning those,
you have problems with lifetimes:

A const& A::eek:perator+(A const& right) const
{
return ? // what to return here that is
// guaranteed to live long enough?
}

You can return smart pointers to solve the lifetime problems:

auto_ptr< A > A::eek:perator+(A const& right) const
{
return auto_ptr< A >(new A(...));
}

However, the returned value now no longer has A as it's base (or
even is an A); thus, you can't write a1 + a2 + a3, for example.

A combination of both approaches gives a proper solution. Make A a
non-polymorphic wrapper that wraps up the implementation. The
operators operate on the wrapper and delegate to the implementation:


struct MyTypeIf;

// MyType has no virtual functions!
struct MyType
{
MyType(MyTypeIf *impl)
: mImpl(impl) { }

MyType operator+(MyType rhs);
...

private:
std::tr1::shared_ptr< MyTypeIf > mImpl;
};

// the interface, could correspond to A
struct MyTypeIf
{
virtual MyType add(MyType const& rhs) = 0;
...
};

MyType MyType::eek:perator+(MyType rhs)
{
return mImpl->add(rhs);
}

// one implementation, could correspond to B
struct MyTypeSomeImpl1
{
...
};

// factory for the implementation
MyType makeSomeImpl1( ... )
{
return MyType(new MyTypeSomeImpl1( ... ));
}


It's a bit verbose, but the overhead becomes negligible when the
number of implementations (derived classes) is high.

There is one more very important benefit to this: You can remove all
implementations from the headers! Especially if the implementing
classes require certain types to be complete, this greatly removes
header dependencies.

This last reason is the major one why this idiom is extremely
important in the c++ language (called pimpl, bridge pattern or
handle/body).
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top