468,168 Members | 1,561 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,168 developers. It's quick & easy.

Inheritance and object factories...HELP!!

Not an experienced c++ programmer here and I've gotten myself a bit
stuck. I'm trying to implement a class lib and I've run into a sticky
problem that I can't solve. I'd appreciate any help that I can get!

Consider 3 classes in the following heirarchy:

base
/ \
deriv1 deriv2
\
deriv3

All derivations are public. These objects represent "values" and have
lots of const member functions that perform some transformation and
return a new, transformed object:

base x;
base y = x.foo();

Now foo() is a const member function so the way it has to work is to
create a new base object and return it. This seems simple enough but I
haven't found a good strategy for doing it in a way that simultaneously
avoids lots of code duplication and doesn't generate memory leaks. Here
are two strategies that I can think of:

=======================================
Strategy 1: Return all objects by value

The member function foo creates a new object on the stack and returns it
by value when needed. No memory leaks, and these are not huge objects so
there isn't much of a penalty for passing them by value.

CONS: The member function foo() can't be implemented in the base class
because it will cause object slicing when used in the derived classes.
So instead I implement:

deriv1 deriv1::foo() const;

and

deriv2 deriv2::foo() const;

The foo() operation is identical for deriv1 and deriv2 except that it
creates and returns a different object. So repeating the code is ugly
and hard to maintain. Furthermore I cannot allow objects of class deriv3
to inherit foo() because of slicing issues. It also causes a problem if
the deriv3 class has a unique member function that doesn't exist in
deriv1 or deriv2. Then the following code is also problematic:

deriv3 A;
deriv3 B = A.foo().unique(); //compile error!

=======================================
Strategy 2: Use references to objects, covariant return and object
factories to implement foo via inheritance

Now we implement foo() in the base class as:

virtual base& base::foo() const {
base& tmp =new_object();
// whatever foo does
return tmp;
}

// along with a base class object factory:
virtual base& new_object() {
// make a base object on
// the heap
return baseObject;
}

In each derived class (e.g. deriv2) we implement foo by using the base
class implementation:

deriv2& deriv2::foo() const {
return static_cast<deriv2&>(base::foo());
}
// we also require an object factory for deriv2 objects
deriv2& deriv2::new_object() {
// make a deriv2 object on
// the heap
return deriv2Object;
}

CONS: memory leaks like crazy. There are no easy ways to clean this up.
The callers can't even do it if they're diligent since there will be
many unnamed temporaries generated by expressions like:

deriv3 U;
double bar = U.foo().functionReturningDouble();

I don't think smart pointers will help, because returning smart pointers
will cause the covariant return paradigm to break.
=======================================

So what to do? The only thing I've been able to think of, is a scheme
where base and its derived objects actually assume ownership for any and
all objects created by member functions. For example:

deriv2 D;
deriv2 E = D.foo()

In this scheme D maintains a smart pointer to the new object but foo
returns a raw pointer as a reference. When D goes out of scope or is
deleted, its destructor cleans up any allocated objects that it owns.
What happens in cases like:

deriv2 F=D;

is a bit unclear to me, but I'm assuming I can work it out. But the
whole idea seems error-prone and it certainly isn't optimal in terms of
memory use.

Can anyone offer any suggestions?

-- Jeff Greenberg
Jul 22 '05 #1
5 1718
Jeff,

I don't think I fully understand your problem without an actual working
piece of code, but from what I see you might benefit from the "pimpl" idiom
here.

In the pimpl idiom you would have a Concrete class which contains a member
variable
_pimpl which is a pointer to an implementation class. The functionality of
the
concrete class is provided by forwarding calls to the implementation class:

class Concrete : public Foo
{
public:
Concrete(){ code to choose which deriv object to create } ;
~Concrete()
{
delete _pimpl;
}
virtual void doFoo( ) { _pimpl->doFoo() ;}
private:
Foo* _pimpl;
};

Deriv1, dervi2, deriv3,
class deriv1 : public Foo
{
public:
virtual void doFoo(){ }

};
// etc, etc

This pattern now allows you to vary the implementation class by using a
different derived
object for the _pimpl. In this way you can return an actual object of class
"concrete" which
has the actual behavior of the various derived objects deriv1, deriv2,
deriv3 etc. Since you
return an actual object, there is no issue about memory leaks, slicing, etc.
( you said somewhere
that the construction of the deriv classes was not expensive, so the copying
semantics would
be ok to implement in Concrete ). If you client is unaware of the actual
type of object (deriv1,
deriv2, etc) and only cares about the public interface of the base class,
this should work.

Does that help? Let me know if I can explain anything better,

dave.
"Jeff Greenberg" <jg******@comcast.net> wrote in message
news:jg****************************@news.supernews .com...
Not an experienced c++ programmer here and I've gotten myself a bit
stuck. I'm trying to implement a class lib and I've run into a sticky
problem that I can't solve. I'd appreciate any help that I can get!

Consider 3 classes in the following heirarchy:

base
/ \
deriv1 deriv2
\
deriv3

All derivations are public. These objects represent "values" and have
lots of const member functions that perform some transformation and
return a new, transformed object:

base x;
base y = x.foo();

Now foo() is a const member function so the way it has to work is to
create a new base object and return it. This seems simple enough but I
haven't found a good strategy for doing it in a way that simultaneously
avoids lots of code duplication and doesn't generate memory leaks. Here
are two strategies that I can think of:

=======================================
Strategy 1: Return all objects by value

The member function foo creates a new object on the stack and returns it
by value when needed. No memory leaks, and these are not huge objects so
there isn't much of a penalty for passing them by value.

CONS: The member function foo() can't be implemented in the base class
because it will cause object slicing when used in the derived classes.
So instead I implement:

deriv1 deriv1::foo() const;

and

deriv2 deriv2::foo() const;

The foo() operation is identical for deriv1 and deriv2 except that it
creates and returns a different object. So repeating the code is ugly
and hard to maintain. Furthermore I cannot allow objects of class deriv3
to inherit foo() because of slicing issues. It also causes a problem if
the deriv3 class has a unique member function that doesn't exist in
deriv1 or deriv2. Then the following code is also problematic:

deriv3 A;
deriv3 B = A.foo().unique(); //compile error!

=======================================
Strategy 2: Use references to objects, covariant return and object
factories to implement foo via inheritance

Now we implement foo() in the base class as:

virtual base& base::foo() const {
base& tmp =new_object();
// whatever foo does
return tmp;
}

// along with a base class object factory:
virtual base& new_object() {
// make a base object on
// the heap
return baseObject;
}

In each derived class (e.g. deriv2) we implement foo by using the base
class implementation:

deriv2& deriv2::foo() const {
return static_cast<deriv2&>(base::foo());
}
// we also require an object factory for deriv2 objects
deriv2& deriv2::new_object() {
// make a deriv2 object on
// the heap
return deriv2Object;
}

CONS: memory leaks like crazy. There are no easy ways to clean this up.
The callers can't even do it if they're diligent since there will be
many unnamed temporaries generated by expressions like:

deriv3 U;
double bar = U.foo().functionReturningDouble();

I don't think smart pointers will help, because returning smart pointers
will cause the covariant return paradigm to break.
=======================================

So what to do? The only thing I've been able to think of, is a scheme
where base and its derived objects actually assume ownership for any and
all objects created by member functions. For example:

deriv2 D;
deriv2 E = D.foo()

In this scheme D maintains a smart pointer to the new object but foo
returns a raw pointer as a reference. When D goes out of scope or is
deleted, its destructor cleans up any allocated objects that it owns.
What happens in cases like:

deriv2 F=D;

is a bit unclear to me, but I'm assuming I can work it out. But the
whole idea seems error-prone and it certainly isn't optimal in terms of
memory use.

Can anyone offer any suggestions?

-- Jeff Greenberg

Jul 22 '05 #2
* Jeff Greenberg:

Consider 3 classes in the following heirarchy:

base
/ \
deriv1 deriv2
\
deriv3

All derivations are public. These objects represent "values" and have
lots of const member functions that perform some transformation and
return a new, transformed object:

base x;
base y = x.foo();
What you mean by "values" seems to be immutable objects.
Now foo() is a const member function so the way it has to work is to
create a new base object and return it. This seems simple enough but I
haven't found a good strategy for doing it in a way that simultaneously
avoids lots of code duplication and doesn't generate memory leaks. Here
are two strategies that I can think of:

=======================================
Strategy 1: Return all objects by value

The member function foo creates a new object on the stack and returns it
by value when needed. No memory leaks, and these are not huge objects so
there isn't much of a penalty for passing them by value.

CONS: The member function foo() can't be implemented in the base class
because it will cause object slicing when used in the derived classes.


Well that isn't quite correct.

One way is to use a protected template function:

class Base
{
protected:
template< class Result >
Result foo_() const
{
return Result();
}
public:
virtual ~Base() {}
virtual Base foo() const { return foo_<Base>(); }
};

class Derived: public Base
{
public:
virtual Derived foo() const { return foo_<Derived>(); }
};

Another way is to use dynamic allocation via a protected virtual
factory function. To avoid memory leaks the foo() result should
then be a smart-pointer, the handle/body-pattern. Smart-pointers
can work with covariance when they're not reseatable. From the
rest of what you write I presume you're aware of why it's not a
good idea with reseatable smart-pointers in this context. However,
an easier solution is to note that anybody wanting a Derived-specific
result know they're dealing with Derived and so can call a Derived-
specific version of foo; this even works with std::auto_ptr:

class Base
{
private:
virtual Base* rawFoo() const { return new Base; }
public:
typedef std::auto_ptr<Base> AutoPtr;

virtual ~Base() {}
AutoPtr foo() const { return AutoPtr( rawFoo() ); }
};

class Derived: public Base
{
private:
virtual Derived* rawFoo() const { return new Derived; }
public:
typedef std::auto_ptr<Derived> AutoPtr;

AutoPtr derivedFoo() const{ return AutoPtr( rawFoo() ); }
};

int main()
{
Derived().foo(); // calls Derived::rawFoo, Base::AutoPtr
Derived().derivedFoo(); // ditto, but now Derived::AutoPtr
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #3
Alf,

Thanks for the reply. I looked at your first suggestion:

In article <41****************@news.individual.net>,
al***@start.no (Alf P. Steinbach) wrote:
> CONS: The member function foo() can't be implemented in the base class
because it will cause object slicing when used in the derived classes.


Well that isn't quite correct.

One way is to use a protected template function:

class Base
{
protected:
template< class Result >
Result foo_() const
{
return Result();
}
public:
virtual ~Base() {}
virtual Base foo() const { return foo_<Base>(); }
};

class Derived: public Base
{
public:
virtual Derived foo() const { return foo_<Derived>(); }
};


Unfortunately, this does not compile (at least on any compiler I have)
because
virtual Derived foo() const { return foo_<Derived>(); }
is an illegal override of
virtual Base foo() const { return foo_<Base>(); }
since Base and Derived are not covariant. Of course it would work if we
were returning Base& and Derived& but that leads back to my original
problem. Did you have something else in mind?
Another way is to use dynamic allocation via a protected virtual
factory function. To avoid memory leaks the foo() result should
then be a smart-pointer, the handle/body-pattern. Smart-pointers
can work with covariance when they're not reseatable. From the
rest of what you write I presume you're aware of why it's not a
good idea with reseatable smart-pointers in this context.
You give me more credit than I deserve. I'm not sure how
"non-reseatable" (is that the same as "non-resetable"?) smart pointers
can help. To be covariant, the return type must be a pointer to a
derived type of the base class return. The smart pointer libs that I'm
aware of all work through templates. For example:

boost::shared_ptr<Base> has no inheritance relationship with
boost:shared_ptr<Derived>. So how does this help?
However,
an easier solution is to note that anybody wanting a Derived-specific
result know they're dealing with Derived and so can call a Derived-
specific version of foo; this even works with std::auto_ptr:

class Base
{
private:
virtual Base* rawFoo() const { return new Base; }
public:
typedef std::auto_ptr<Base> AutoPtr;

virtual ~Base() {}
AutoPtr foo() const { return AutoPtr( rawFoo() ); }
};

class Derived: public Base
{
private:
virtual Derived* rawFoo() const { return new Derived; }
public:
typedef std::auto_ptr<Derived> AutoPtr;

AutoPtr derivedFoo() const{ return AutoPtr( rawFoo() ); }
};

int main()
{
Derived().foo(); // calls Derived::rawFoo, Base::AutoPtr
Derived().derivedFoo(); // ditto, but now Derived::AutoPtr
}


This would work for many applications but in this application it leads
to unacceptable syntax in the calling program. Operations like "foo()"
represent generic mathematical transformations that are logically
identical so it would not make much sense to write:

Base().sqrt();

and then

Derived().derivedSqrt();

when both operations imply the same mathematical transformation.
Requiring such syntax would lead to a user revolt :)

-- Jeff
Jul 22 '05 #4
* Jeff Greenberg:
Alf,

Thanks for the reply. I looked at your first suggestion:

In article <41****************@news.individual.net>,
al***@start.no (Alf P. Steinbach) wrote:
>
CONS: The member function foo() can't be implemented in the base class
because it will cause object slicing when used in the derived classes.


Well that isn't quite correct.

One way is to use a protected template function:

class Base
{
protected:
template< class Result >
Result foo_() const
{
return Result();
}
public:
virtual ~Base() {}
virtual Base foo() const { return foo_<Base>(); }
};

class Derived: public Base
{
public:
virtual Derived foo() const { return foo_<Derived>(); }
};


Unfortunately, this does not compile (at least on any compiler I have)
because
virtual Derived foo() const { return foo_<Derived>(); }


is an illegal override of
virtual Base foo() const { return foo_<Base>(); }


since Base and Derived are not covariant. Of course it would work if we
were returning Base& and Derived& but that leads back to my original
problem. Did you have something else in mind?


No it was just sloppy thinking in a hasty reply. Full points on creativity,
zero on attention to detail. The following slight adjustment compiles (;-)):
#include <iostream>
#include <memory>

class Base
{
protected:
template< class Result >
Result foo_() const
{
return Result();
}
public:
virtual ~Base() {}
virtual Base foo( Base* = 0 ) const { return foo_<Base>(); }
};

class Derived: public Base
{
public:
virtual Derived foo( Derived* = 0 ) const
{ return foo_<Derived>(); }

virtual Base foo( Base* ) const
{ return foo( static_cast<Derived*>(0) ); }
};

int main()
{
Base().foo();
Derived().foo();
}
The implementation of Derived::Foo(Base*) in terms of Derived::foo(Derived*)
is to avoid O(n^2) overrides in an n-classes inheritance chain. It does
involve a lot of object creation and destruction, though, modulo optimization.
However as I understood it that was OK.

Another way is to use dynamic allocation via a protected virtual
factory function. To avoid memory leaks the foo() result should
then be a smart-pointer, the handle/body-pattern. Smart-pointers
can work with covariance when they're not reseatable. From the
rest of what you write I presume you're aware of why it's not a
good idea with reseatable smart-pointers in this context.


You give me more credit than I deserve. I'm not sure how
"non-reseatable" (is that the same as "non-resetable"?) smart pointers
can help. To be covariant, the return type must be a pointer to a
derived type of the base class return. The smart pointer libs that I'm
aware of all work through templates. For example:

boost::shared_ptr<Base> has no inheritance relationship with
boost:shared_ptr<Derived>. So how does this help?


Uh, hm, well... Checking it out it's no good to return a temporary as a
reference to const because function return value is one of the exceptions to
the general rule that the temporary should persist. Dang!

But hey, now it seems clear why Andrei was asking about lifetime of
temporaries created for arguments.

Temporary storage is in general not good enough for a reference result because
that result might be passed back up the function call chain, or bound to
a local reference, or whatever. That's one of those situations where the
language isn't exactly helpful. The FAQ's solution to such dilemmas is to
use a comment with a stern warning about what the client should not ever do.

In the following code I haven't addressed the issue of factoring out the
common foo() functionality, because you don't specify anything about that.

Nor does it ensure that all access is via smart-pointers, because that
depends on the concrete design, and would just clutter things here, and
most of all, this is untested code -- it compiles, but that's it... ;-)
#include <memory>

class Base
{
protected:
class TempPtrStorage;

public:
class Ptr
{
friend class TempPtrStorage;
private:
Ptr( Ptr const& ); // Nope.
Ptr& operator=( Ptr const& ); // Nope.

protected:
std::auto_ptr<Base> myP;

Ptr( Base* p ): myP( p ) {}
public:
Base const* operator->() const { return myP.get(); }
};

protected:
class TempPtrStorage
{
friend class Base;
private:
mutable std::auto_ptr<Ptr> myStorage; // Could/should be optimized.
protected:
template< class PtrType, class Contained >
PtrType& smartPointer( Contained* pContained ) const
{
myStorage.reset( new PtrType( pContained ) );
return *static_cast<PtrType*>( myStorage.get() );
}
};

template< class PtrType, class Contained >
PtrType& smartPointer( TempPtrStorage const& storage, Contained*
pContained ) const
{
return storage.smartPointer<PtrType>( pContained );
}

public:
// Bind the result to a ref, or take its address, then you're fired.
virtual Base::Ptr const& foo(
TempPtrStorage const& stg = TempPtrStorage()
) const
{
return smartPointer<Base::Ptr>( stg, new Base() );
}
};

class Derived: public Base
{
public:
class Ptr: public Base::Ptr
{
friend class TempPtrStorage;
protected:
Ptr( Derived* p ): Base::Ptr( p ) {}
public:
Derived const* operator->() const
{
return static_cast<Derived*>( myP.get() );
}
};

// Bind the result to a ref, or take its address, then you're fired.
virtual Derived::Ptr const& foo(
TempPtrStorage const& stg = TempPtrStorage()
) const
{
return smartPointer<Derived::Ptr>( stg, new Derived() );
}
};

int main()
{
Derived d;
Base& bRef = d;

bRef.foo(); // Calls Derived::foo.
}

However,
an easier solution is to note that anybody wanting a Derived-specific
result know they're dealing with Derived and so can call a Derived-
specific version of foo; this even works with std::auto_ptr:

class Base
{
private:
virtual Base* rawFoo() const { return new Base; }
public:
typedef std::auto_ptr<Base> AutoPtr;

virtual ~Base() {}
AutoPtr foo() const { return AutoPtr( rawFoo() ); }
};

class Derived: public Base
{
private:
virtual Derived* rawFoo() const { return new Derived; }
public:
typedef std::auto_ptr<Derived> AutoPtr;

AutoPtr derivedFoo() const{ return AutoPtr( rawFoo() ); }
};

int main()
{
Derived().foo(); // calls Derived::rawFoo, Base::AutoPtr
Derived().derivedFoo(); // ditto, but now Derived::AutoPtr
}


This would work for many applications but in this application it leads
to unacceptable syntax in the calling program. Operations like "foo()"
represent generic mathematical transformations that are logically
identical so it would not make much sense to write:

Base().sqrt();

and then

Derived().derivedSqrt();

when both operations imply the same mathematical transformation.
Requiring such syntax would lead to a user revolt :)


Well I think you could just use the dummy argument trick exemplified
at top, to call both functions 'sqrt' (differentiating on argument type
instead of name, where the client code never uses that argument).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #5
In article <41****************@news.individual.net>,
al***@start.no (Alf P. Steinbach) wrote:
<......snip........>

No it was just sloppy thinking in a hasty reply. Full points on creativity,
zero on attention to detail. The following slight adjustment compiles (;-)):
#include <iostream>
#include <memory>

class Base
{
protected:
template< class Result >
Result foo_() const
{
return Result();
}
public:
virtual ~Base() {}
virtual Base foo( Base* = 0 ) const { return foo_<Base>(); }
};

class Derived: public Base
{
public:
virtual Derived foo( Derived* = 0 ) const
{ return foo_<Derived>(); }

virtual Base foo( Base* ) const
{ return foo( static_cast<Derived*>(0) ); }
};

int main()
{
Base().foo();
Derived().foo();
}
The implementation of Derived::Foo(Base*) in terms of Derived::foo(Derived*)
is to avoid O(n^2) overrides in an n-classes inheritance chain. It does
involve a lot of object creation and destruction, though, modulo optimization.
However as I understood it that was OK.


Very clever! I've never seen that dummy argument trick before. I don't
have time to try it out right now but I will in the next day or
so...just might do the trick!

-- Jeff
Jul 22 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Mark F. Haigh | last post: by
1 post views Thread by Patrick Stinson | last post: by
3 posts views Thread by YUY0x7 | last post: by
6 posts views Thread by Graham Pengelly | last post: by
3 posts views Thread by BakelNB | last post: by
6 posts views Thread by Slain | last post: by
reply views Thread by kamranasdasdas | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.