By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,686 Members | 1,558 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,686 IT Pros & Developers. It's quick & easy.

Design problem: Factory pattern needs 'static virtual'?

P: n/a
I need a simple object serialization, where loading an object from
file looks like this:

Foo* foo1 = FooFactory::create("./saved/foo1.a321f23d");
Foo* foo2 = FooFactory::create("./saved/foo2.eb287ac8");

Now, Foo is an abstract base class, and FooFactory contains a static
function which again calls static create functions on Foo1 or Foo2
(see code for all classes below). The problem is that all these
functions are static, but I also want them to be part of the (virtual)
Foo interface. But virtual static functions are not allowed.

You might say that Foo1::create(...) should not be a member function,
but just a global function outside of Foo1. But I want classes derived
from Foo1 to be able to inherit or override create(...).

How should I design this properly?

Thanks! Markus

<code>

class Foo {
public:
// virtual static std::string type() const = 0; // not
allowed
// virtual static Foo* create(const std::string& dataLocation) =
0; // not allowed
// other functions that constiute the Foo
interface
};

class Foo1 : public Foo {
public:
static std::string type() {
static const std::string t = "Foo1";
return t;
}
static Foo* create(const std::string& dataLocation) {
return new Foo1(/* parameters according to data read from
dataLocation*/);
}
};
class Foo2 : public Foo1 {
public:
static std::string type() {
static const std::string t = "Foo2";
return t;
}
// function "create" is derived from
Foo1
};

namespace FooFactory {
Foo* create(const std::string& dataLocation) {
const std::string type =
getType(dataLocation);
if(type == Foo1::type()){
return Foo1::create(dataLocation);
}
else if(type == Foo2::type()){
return Foo2::create(dataLocation);
}
}
} // end namespace

</code>
Jan 3 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
On Jan 3, 11:49*pm, Markus Dehmann <markus.dehm...@gmail.comwrote:
I need a simple object serialization, where loading an object from
file looks like this:

* Foo* foo1 = FooFactory::create("./saved/foo1.a321f23d");
* Foo* foo2 = FooFactory::create("./saved/foo2.eb287ac8");

Now, Foo is an abstract base class, and FooFactory contains a static
function which again calls static create functions on Foo1 or Foo2
(see code for all classes below). The problem is that all these
functions are static, but I also want them to be part of the (virtual)
Foo interface. But virtual static functions are not allowed.

You might say that Foo1::create(...) should not be a member function,
but just a global function outside of Foo1. But I want classes derived
from Foo1 to be able to inherit or override create(...).
How should I design this properly?
namespace FooFactory {
* Foo* create(const std::string& dataLocation) {
* * const std::string type =
getType(dataLocation);
* * if(type == Foo1::type()){
* * * return Foo1::create(dataLocation);
* * }
* * else if(type == Foo2::type()){
* * * return Foo2::create(dataLocation);
* * }
* }
look up "static polymorphism" or named conformance to an interface

Simply put , use a static create function and if a derived wishes to
override it adds its own static create function, which hides that in
the base class otherwise the compiler will find the base class
version, In fact there is no need for derivation, as any class with a
static create function , or whose base has a static create function
can be used, assuming the return type is viable.

regards
Andy Little

Jan 4 '08 #2

P: n/a
On Jan 4, 12:49 am, Markus Dehmann <markus.dehm...@gmail.comwrote:
I need a simple object serialization, where loading an object from
file looks like this:
Foo* foo1 = FooFactory::create("./saved/foo1.a321f23d");
Foo* foo2 = FooFactory::create("./saved/foo2.eb287ac8");
Now, Foo is an abstract base class, and FooFactory contains a
static function which again calls static create functions on
Foo1 or Foo2 (see code for all classes below). The problem is
that all these functions are static, but I also want them to
be part of the (virtual) Foo interface. But virtual static
functions are not allowed.
You might say that Foo1::create(...) should not be a member
function, but just a global function outside of Foo1. But I
want classes derived from Foo1 to be able to inherit or
override create(...).
I'm not sure I understand what you're asking for. You have
different derived classes of Foo, each with its own function
create. You want the compiler to somehow call the correct
instance of create, according to the dynamic type. But the
dynamic type of what? How do you determine which Foo??::create
should be called?
How should I design this properly?
<code>
class Foo {
public:
// virtual static std::string type() const = 0; // not
allowed
// virtual static Foo* create(const std::string& dataLocation) =
0; // not allowed
// other functions that constiute the Foo
interface
};
class Foo1 : public Foo {
public:
static std::string type() {
static const std::string t = "Foo1";
return t;
}
static Foo* create(const std::string& dataLocation) {
return new Foo1(/* parameters according to data read from
dataLocation*/);
}};
class Foo2 : public Foo1 {
public:
static std::string type() {
static const std::string t = "Foo2";
return t;
}
// function "create" is derived from
Foo1
};
namespace FooFactory {
Foo* create(const std::string& dataLocation) {
const std::string type =
getType(dataLocation);
if(type == Foo1::type()){
return Foo1::create(dataLocation);
}
else if(type == Foo2::type()){
return Foo2::create(dataLocation);
}
}
} // end namespace
</code>
Wouldn't some sort of table be more appropriate? Say an
std::map< std::string, Foo* (*)( std::string ) >. With:

typedef std::map< std::string, Foo* (*)( std::string ) >
FooFactoryMap ;
FooFactoryMap ourMap ;

Foo*
create(
std::string const& dataLocation )
{
FooFactoryMap::const_iterator
entry
= ourMap.find( getType( dataLocation ) ) ;
return entry == ourMap.end()
? NULL
: (*entry->second)() ;
}

You'll have to arrange to initialize the map somehow, but that
shouldn't be any more of a bother than maintaining all of your
if's.

James Kanze (GABI Software) mailto:ja*********@gmail.com
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34

Jan 4 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.