Avoiding templates, alternative design?

Y

Yves Dhondt

Hello,

Currently I have the following "design":

class A { ... };
class B : public A { ... };
class C : public A { ... };

class Z {
private:
A *a;
public:
Z() { a = new A(); };
~Z() { delete a; };
A *GetObject() { return a; };
};

int main() {
Z *z = new Z();

A *temp = z->GetObject();

delete z;
return 0;
}

Now I want Z being able to use B or C in stead of A. So when creating Z
I should somehow be able to specify what it should use (A, B or C).
The easiest way that comes to mind is using templates to specify what
class type I want to use in my instance of Z.

template<class T> Z {
private:
T *t;
public:
Z() { t = new T(); };
~Z() { delete t; };
T *GetObject() { return t; }
};

int main() {
Z<C> *z = new Z<C>();

C *temp = z->GetObject();

delete z;
return 0;
}

But I would like to avoid templates (plans for porting the code to
embedded). Is there a better/other way of doing this?

TIA

Yves
 
M

Mark A. Gibbs

Yves said:
Now I want Z being able to use B or C in stead of A. So when creating Z
I should somehow be able to specify what it should use (A, B or C). The
easiest way that comes to mind is using templates to specify what class
type I want to use in my instance of Z.

You could try this:

class Z {
private:
A *a;
public:
enum contained_type {
ctA,
ctB,
ctC
};

Z(contained_type t) {
switch (t) {
case ctA:
a = new A();
break;
case ctB:
a = new B();
break;
case ctC:
a = new C();
break;
}
};
~Z() { delete a; };
A *GetObject() { return a; };
};

There are other options too, of course. You could do something like this:

class Z {
private:
A *a;
public:
Z(A* p) : p(a) {};
~Z() { delete a; };
A *GetObject() { return a; };
};

Indi

--
Mark A. Gibbs (aka. Indi)
Administrator
#c++ on irc.Rizon.net

http://ca.geocities.com/[email protected]/
(temporary website)
 
P

puzzlecracker

Mark said:
You could try this:

class Z {
private:
A *a;
public:
enum contained_type {
ctA,
ctB,
ctC
};

Z(contained_type t) {
switch (t) {
case ctA:
a = new A();
break;
case ctB:
a = new B();
break;
case ctC:
a = new C();
break;
}
};
~Z() { delete a; };
A *GetObject() { return a; };
};

There are other options too, of course. You could do something like this:

class Z {
private:
A *a;
public:
Z(A* p) : p(a) {};
~Z() { delete a; };
A *GetObject() { return a; };
};

Indi

--
Mark A. Gibbs (aka. Indi)
Administrator
#c++ on irc.Rizon.net

http://ca.geocities.com/[email protected]/
(temporary website)

Is the question about how to implement the factory????
demn, but it looks like it
 
G

Gianni Mariani

Yves said:
Hello,

Currently I have the following "design":

class A { ... };

Make sure A has a virtual destuctor (in this case).

class A { public: virtual ~A(){} };
class B : public A { ... };
class C : public A { ... };

class Z {
private:
A *a;
public:
Z() { a = new A(); };
don't need ';' after func defs.
~Z() { delete a; };
don't need ';' after func defs.
A *GetObject() { return a; };
don't need ';' after func defs.
};

int main() {
Z *z = new Z();

A *temp = z->GetObject();

delete z;
return 0;
}

Now I want Z being able to use B or C in stead of A. So when creating Z
I should somehow be able to specify what it should use (A, B or C). The
easiest way that comes to mind is using templates to specify what class
type I want to use in my instance of Z.

template<class T> Z {
private:
T *t;
public:
Z() { t = new T(); };

don't need ';' after func defs.
~Z() { delete t; };

don't need ';' after func defs.
T *GetObject() { return t; }
};

class Z {
private:
A *a;
Z() {}
public:
Z( const char * key )
: a( FactoryForA( key ) )
{}
~Z() { delete a; }
A *GetObject() { return a; };
};

There is a generic factory example in the Austria C++ library.

In this case you would "register" the factories for B and C (and A if A
can be instantiated).

AT_MakeFactory0P( "B", B, A, DKy );
AT_MakeFactory0P( "C", C, A, DKy );
These registrations would be in a .cpp file and not visible to the rest
of the program.

A * FactoryForA( const char * key )
{
A * a = at::FactoryRegister< Interface, DKy>::Get().Create( key )();

// might return null a - probably need to throw if that's the case

return a;
}

Z zb( "B" ); // Will create a B object
Z zc( "C" ); // Will create a C object

What's the purpose of the Z wrapper ? It looks awfully like a std::auto_ptr.

Disclaimer : all the code I wrote above is intested ...
 
C

Chris \( Val \)

| Hello,
|
| Currently I have the following "design":
|
| class A { ... };
| class B : public A { ... };
| class C : public A { ... };
|
| class Z {
| private:
| A *a;
| public:
| Z() { a = new A(); };
| ~Z() { delete a; };
| A *GetObject() { return a; };
| };
|
| int main() {
| Z *z = new Z();
|
| A *temp = z->GetObject();
|
| delete z;
| return 0;
| }
|
| Now I want Z being able to use B or C in stead of A. So when creating Z
| I should somehow be able to specify what it should use (A, B or C).
| The easiest way that comes to mind is using templates to specify what
| class type I want to use in my instance of Z.
|
| template<class T> Z {
| private:
| T *t;
| public:
| Z() { t = new T(); };
| ~Z() { delete t; };
| T *GetObject() { return t; }
| };
|
| int main() {
| Z<C> *z = new Z<C>();
|
| C *temp = z->GetObject();
|
| delete z;
| return 0;
| }
|
| But I would like to avoid templates (plans for porting the code to
| embedded). Is there a better/other way of doing this?

Polymorphism might be what you're looking for ?

Here's a quick example, if you don't mind the syntax:

class A { public: virtual void P()
{ std::cout << "A::p()\n"; } };
class B : public A { public: void P()
{ std::cout << "B::p()\n"; } };
class C : public A { public: void P()
{ std::cout << "C::p()\n"; } };

class Z
{
private:
A *a;
public:
Z( A* aa ) : a( aa ) {}
~Z() { delete a; };

A *GetObject() { return a; };
};

int main() {
Z *z = new Z( new B );
A *temp = z->GetObject();
temp->P();
delete z;

z = new Z( new C );
temp = z->GetObject();
temp->P();
delete z;

return 0;
}

Cheers.
Chris Val

PS: I have gone along with you're naming scheme, but
please choose better names for your identifiers
if you can.
 

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
474,199
Messages
2,571,045
Members
47,643
Latest member
ashutoshjha_1101

Latest Threads

Top