Re: Using a template to 'new' a forward declared class
On May 20, 9:08 pm, "Ole Nielsby" <ole.nielsby@tekare-you-a-spammer?
logisk.dk> wrote:
I want to create (with new) and delete a forward declared class.
You can't. The type must be complete before the new expression.
(I'll call them Zorgs here - the real-life Zorks are platform-dependent
objects (mutexes, timestamps etc.) used by a cross-platform scripting
engine. When the scripting engine is embedded in an application, a
platform-specific support library is linked in.)
The usual solution here is either the compilation firewall idiom
or a factory function. (If you're new'ing the objects, a
factory function is probably preferred, but it requires all
instances to be new'ed.)
My first attempt goes here:
---code begin (library)---
class Zorg_implementation; //to be defined by another library
class Zorg {
public:
Zorg(): zi(new Zorg_implementation) {} //compile error
~Zorg() {delete zi;}
private:
Zorg_implementation *zi;};
---code end---
which won't compile
(VC8 says: no appropriate default constructor available)
More generally, "new Toto" is only legal if Toto is a complete
type.
Then I stuffed it in a dummy template:
---code begin---
class Zorg_implementation; //to be defined by another library
template <typename Z> class Zorg_t {
public:
Zorg_t(): zi(new Z) {}
~Zorg_t() {delete zi;}
private:
Z *zi;};
typedef Zorg_template<Zorg_implementation> Zorg;
I presume that Zorg_template is a typo for Zorg_t, here.
---code end---
If you never actually instantiation a Zorg, the constructor is
never instantiated, and there is no problem. If whenever you
create an instance of Zorg, Zorg_implementation has been fully
defined, there is also no problem. Otherwise, you will
encounter the same problem as above.
The main difference, of course, is that in your first version,
you will get a compiler error every time the compiler sees the
definition of Zorg (without first having seen the definition of
Zorg_implementation). In the second, you will only get a
compiler error if you try to actually create an instance of Zorg
at a point where Zorg_implementation has not been fully defined.
This compiles and runs fine. Zorg_wrapper instances can be created
by one library, while another library defines the Zorg_implementation cla=
ss.
This strikes me as odd - I would expect the templated version to have the
same effect as the simple version.
Can anybody explain what is going on here? Is this standard behaviour
or a VC8 quirk? Can I rely on it - or should I define a factory class?
Without knowing more about the rest of the code, it is difficult
to say. In these sort of cases, I tend to favor factories,
however. In the exact example you show, of course, it would be
sufficient that the constructor and destructor not be inline,
and that Zorg_implementation be fully defined in the module
where they were defined.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34