-
July 14th, 2009, 05:21 AM
#1
Construction from abstract base pointer
I have a "BaseAbstractClass", and three derived classes, "ClassA", "ClassB" and "ClassC".
All three of my classes A,B and C can be constructed from another class. ie, for class a, I have:
Code:
ClassA(ClassA& i);
ClassA(ClassB& i);
ClassA(ClassC& i);
but not ClassA(ClassBase& i);
I would like to know how to construct an object of class ClassA, from a pointer to BaseClass, which could be any of ClassA, B or C?
This doesn't work, kind of obviously...
Code:
//pb is of type BaseClass*
ClassA aObj(*pB);
error is no matching function for call to `ClassA::ClassA(ClassBase&)'
I guess I should write a ClassA(ClassBase* ip), but I'm unsure how to implement that.
-
July 14th, 2009, 05:38 AM
#2
Re: Construction from abstract base pointer
I would do something like this:
Code:
class ClassA;
class ClassBase {
public:
virtual ClassA constructClassA() = 0;
}
class ClassA : public ClassBase {
public:
virtual ClassA constructClassA() { return ClassA(*this); }
}
class ClassB : public ClassBase {
public:
virtual ClassA constructClassA() { return ClassA(*this); }
}
class ClassC : public ClassBase {
public:
virtual classA constructClassA() { return ClassA(*this); }
}
ClassA aObj = pB->constructClassA();
More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf
Premature optimization is the root of all evil --Donald E. Knuth
Please read Information on posting before posting, especially the info on using [code] tags.
-
July 14th, 2009, 06:36 AM
#3
Re: Construction from abstract base pointer
Maybe you can use the visitor pattern to create an instance of Class A?
Code:
struct IAbstractVisitor
{
virtual IAbstractVisitor()
{
}
virtual void accept( ClassA& op ) = 0;
virtual void accept( ClassB& op ) = 0;
virtual void accept( ClassC& op ) = 0;
};
struct BaseClass
{
virtual void visit( IAbstractVisitor& visitor ) = 0;
};
struct ClassA
{
void visit( IAbstractVisitor& visitor )
{
visitor.accept( *this );
}
};
struct ClassB
{
void visit( IAbstractVisitor& visitor )
{
visitor.accept( *this );
}
};
struct ClassB
{
void visit( IAbstractVisitor& visitor )
{
visitor.accept( *this );
}
};
struct ClassACreator : public IAbstractVisitor
{
ClassA instance_;
void visit( ClassA& op )
{
// invoke copy constructor with arg type ClassA
instance_ = ClassA( op );
}
void visit( ClassB& op )
{
// invoke copy constructor with arg type ClassB
instance_ = ClassA( op );
}
void visit( ClassC& op )
{
// invoke copy constructor with arg type ClassC
instance_ = ClassA( op );
}
};
ClassA makeClassA( BaseClass& base )
{
ClassACreator Creator;
base.accept( base );
return Creator.instance_;
}
There are one and a half major drawbacks in this approach:
1) you have to modify BaseClass, ClassA, ClassB and ClassC
2) calling makeClassA includes two copy constructor calls. I only count this half a drawback because the compiler might do some optimizations. It can be removed completely by returning pointers to the ABC instead of objects.
A templated creator class removes duplicate code:
Code:
template<typename T>
struct ClassCreator
{
T instance_;
ClassCreator( BaseClass& base )
{
base.accept( *this );
}
void visit( ClassA& op )
{
// construct from ClassA
instance_ = T( op );
}
void visit( ClassB& op )
{
// construct from ClassB
instance_ = T( op );
}
void visit( ClassC& op )
{
// construct from ClassC
instance_ = T( op );
}
};
template<typename T>
T make( BaseClass& base )
{
return ClassCreator<T>( base ).instance_;
}
Edit:
I found an possibly unwanted behaviour when using my code: Since make returns an object by value one additional call to the copy constructor of the same type will be made. I don´t know if this issue renders the whole thing useless.
Last edited by GNiewerth; July 14th, 2009 at 07:04 AM.
- Guido
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|