I'm refactoring a single 3000+-line class with a tangled web of conditionals and switches into a set of worker classes. Previously part of the constructor would select which "type" of thing to use via code like the following:
enum Type { FOO, BAR, BAZ };
Type choices[] = { FOO, FOO, BAR, BAZ }; // weighted towards FOO
m_type = choices[rand()%4];
[...later...]
void Run() {
switch (m_type) {
case FOO: do_foo(); break;
case BAR: do_bar(); break;
case BAZ: do_baz(); break;
}
}
After refactoring I have separate TypeFoo, TypeBar and TypeBaz classes that each have their own Run() methods to do their job. Sadly, its complicated the class selection code. I don't know of any way to keep a list of possible classes to construct, so I have this:
Type *m_type;
switch (mrand()%4) {
case 0: case 1: m_type = new TypeFoo(); break;
case 1: m_type = new TypeBar(); break;
case 2: m_type = new TypeBaz(); break;
}
This is still worth the change because this initialisation code is not called regularly, but its now harder to modify this list, change weightings, etc.
Is there a relatively straightforward to achieve the clarity of the original code?
The answer is : a base class and an array of function pointers can help you do that.
struct Base { virtual ~Base() {} }; //make ~Base() virtual
struct Foo : Base {};
struct Bar : Base {};
struct Baz : Base {};
template<typename T>
Base *Create() { return new T(); }
typedef Base* (*CreateFn)();
CreateFn create[] =
{
&Create<Foo>,
&Create<Foo>, // weighted towards FOO
&Create<Bar>,
&Create<Baz>
};
const size_t fncount = sizeof(create)/sizeof(*create);
Base *Create()
{
return create[rand() % fncount](); //forward the call
}
Then use it as (ideone demo):
int main() {
Base *obj = Create();
//work with obj using the common interface in Base
delete obj; //ok,
//the virtual ~Base() lets you do it
//in a well-defined way
return 0;
}
I would suggest creating a common base class (if you've not already got one) and then using a factory class to encapsulate the creation process. The factory would just return a pointer to your base class which has the prototype run method.
Something along these lines:
class Type
{
virtual void Run() = 0;
};
class TypeFoo : public Type
{
public:
TypeFoo() {};
virtual void Run() {};
static Type* Create() { return new TypeFoo(); };
};
class TypeBar : public Type
{
public:
TypeBar() {};
virtual void Run() {};
static Type* Create() { return new TypeBar(); };
};
class TypeBaz : public Type
{
public:
TypeBaz() {};
virtual void Run() {};
static Type* Create() { return new TypeBaz(); };
};
class TypeFactory
{
typedef Type* (*CreateFn)();
public:
static Type* RandomTypeFooWeighted()
{
CreateFn create[] =
{
TypeFoo::Create,
TypeFoo::Create, // weighted towards FOO
TypeBar::Create,
TypeBaz::Create
};
const int fncount = sizeof(create)/sizeof(*create);
return create[ rand()%fncount ]();
}
};
So to use it you can just call:
Type *t = TypeFactory::RandomTypeFooWeighted();
Credit to Nawaz for the function pointer bits and bobs.
Related
I have a situation that I am attempting to write some c++ code to implement and I think I need to use templates but I am unsure. I don't think I understand templates well enough and just want to know if I am on the right track. I have never implemented a class that requires templates before.
I have a base class that needs to instantiate a new class and store it on a list for future access. The class that needs to be instantiated is derived from a base class that has one virtual method. After the class is instantiated, this method is called and the new instance is stored on a list. Another method is provided to get the instantiated object.
Say the virtual class is named foo:
class foo
{
public:
virtual void process() = 0;
}
the user would create a class bar:
class bar : public foo
{
public:
void process() {};
}
The class that I think needs to be a template class:
class Filter<Foo* T>
{
public:
// use value junk to derive foo
// and put the new instance on a std::list
add(Junk* junk);
T get();
private:
std::list<T> mFooList;
}
void Filter::add(Junk* junk)
{
T* foo = new T();
foo.p(junk);
mFooList.push_back(foo);
}
T* Filter::get()
{
if(!mFoolist.empty())
{
T* res = mFooList.back();
mFooList.pop_back();
return res;
}
return nullptr;
}
You don't need to use a templatevin this situation. In c++ a derived class can be assigned to a pointer of the base class. You can just use foo pointers.
class foo
{
public:
virtual void process();
};
class bar1: public foo
{
public:
void process();
};
class bar2 : public foo
{
public:
void process();
};
class filter
{
private:
std::list<foo*> _foos;
public:
foo* get();
void add(foo* f);
};
void filter::add(foo* f)
{
_foos.push_back(f);
}
foo* filter::get()
{
if(!_foos.empty())
{
return _foos.pop_back();
}
return nullptr;
}
You can then just add and get foos and bars
filter fil;
fil.add(new foo());
fill.add(new bar1());
fill.add(new bar2());
foo f = fill.get();
while(f != nullptr)
{
f->process();
delete f;
f = fil.get();
}
My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.
I was having a discussion with a co-worker about templates, and one of things we were talking about is that given a class such as the following, how would you get away with having the switch statement via usage of templates?
enum EVersion
{
Version_1,
Version_2,
};
class CBar
{
...
public:
EVersion ver;
};
class CFoo
{
void Reset()
{
switch (pBar->ver)
{
case Version_1:
TemplateHelperMethod<Version_1>::DoSomething();
break;
case Version_2:
TemplateHelperMethod<Version_2>::DoSomething();
break;
}
}
CBar *pBar;
};
CFoo* pFoo = new CFoo(pBar);
pFoo->Reset();
One solution is to create a derived templated class, and move the function to the derived class that needs to use a switch statement based on the version.
class CFoo
{
...
CBar *pBar;
};
template <EVersion Ver>
class CFoo2 : public Foo
{
void Reset()
{
TemplateHelperMethod<Ver>::DoSomething();
}
};
CFoo2<Version_2>* pFoo = new CFoo2<Version_2>(pBar);
pFoo->Reset();
However, my co-worker suggested that it's possible to keep the original function in the base class, and just change it to a templated method (something like below). However, I am a little dense on how that would work. How would you use the derived class to pass the type to the templated method now? If anyone has any ideas, please let me know. Thanks.
class CFoo
{
template <EVersion Ver>
void Reset()
{
TemplateHelperMethod<Ver>::DoSomething();
}
CBar *pBar;
};
template <EVersion Ver>
class CFoo2 : public Foo
{
// does anything go here?
};
CFoo2<Version_2>* pFoo = new CFoo2<Version_2>(pBar);
pFoo->Reset();
OR
CFoo* pFoo = new CFoo(pBar);
// Can you do this? since CFoo2 derives from CFoo
// and has no additional members...
CFoo2<Version_2>* pFoo2 = static_cast<CFoo2<Version_2>*>(pFoo);
pFoo2->Reset();
I think what your co-worker suggested is not possible since pBar->ver is not a compile time constant. You cannot use it as template parameter.
The correct solution to remove a switch on a runtime variable is runtime polymorphism
struct Version
{
virtual ~Version() = default;
virtual void DoSomething() = 0;
};
class CBar
{
public:
Version& ver;
};
class CFoo
{
public:
void Reset()
{
pBar->ver.DoSomething();
}
CBar *pBar;
};
If you make CBar::ver a compile time constant you can use it to specialize CFoo on it.
template<EVersion Version>
struct CBar
{
EVersion version = Version;
};
template<EVersion Version>
struct CFoo
{
void Reset();
CBar<Version> pBar;
};
template<>
void CFoo<Version_1>::Reset()
{
}
template<>
void CFoo<Version_2>::Reset()
{
}
This question is regarding copying and pointer polymorphism. Consider the code below. We have two classes: Base and Derived, which are just regular objects. Then we've got class Foo, which has a pointer to Base as its only member.
The typical usage of Foo is described in the main function. The input to Foo::SetMemberX may or may not be a temporary object.
The problem is that I want Foo::SetMember to create a proper copy of the passed object, and assign its address as a Base* to Foo::mMember.
I've managed to come up with 4 possible solution, none of which seem very elegant to me. The first three are shown in the code below in Foo::SetMember1, Foo::SetMember2, and Foo::SetMember3. The 4th option is to leave the memory allocation to the user (ex. foo.SetMember(new Derived())), which is not very desirable for obvious memory safety issues. Foo should be responsible for memory management, not the user.
#include <iostream>
template <typename tBase, typename tPointer>
void ClonePointer(tBase*& destination, const tPointer* pointer)
{
destination = static_cast<tBase*>(new tPointer(*pointer));
}
// Base can be a virtual class
class Base
{
public:
virtual void Function()
{
std::cout << "Base::Function()" << std::endl;
}
virtual Base* Clone() const = 0;
};
class Derived : public Base
{
public:
virtual void Function()
{
std::cout << "Derived::Function()" << std::endl;
}
virtual Base* Clone() const
{
return new Derived(*this);
}
};
class Foo
{
public:
Foo() : mMember(NULL) { }
~Foo()
{
if (mMember != NULL)
{
delete mMember;
mMember = NULL;
}
}
template <typename T>
void SetMember1(const T& t)
{
if (mMember != NULL)
{
delete mMember;
mMember = NULL;
}
ClonePointer(mMember, &t);
}
void SetMember2(const Base& b)
{
mMember = b.Clone();
}
template <typename T>
void SetMember3(const T& t)
{
if (mMember != NULL)
{
delete mMember;
mMember = NULL;
}
mMember = new T(t);
}
Base& GetMember()
{
return *mMember;
}
private:
Base* mMember;
};
int main(int argc, char** argv)
{
{
Foo f1;
Foo f2;
Foo f3;
// The input may or may not be a tempoary/RValue reference
f1.SetMember1(Derived());
f2.SetMember2(Derived());
f3.SetMember3(Derived());
f1.GetMember().Function();
f2.GetMember().Function();
f3.GetMember().Function();
}
// Output:
// Derived::Function();
// Derived::Function();
// Derived::Function();
system("pause"); // for quick testing
}
The problem with the first method (Foo::SetMember1) is that I have a random, free, template function, and a template accessore (see the problem with the third method below).
The problem with the second method (Foo::SetMember2) is that every derived class must implement its own Clone function. This is too much boilerplate code for the class user, as there will be a lot of classes deriving from Base. If I could somehow automate this, or create a base Cloneable class (without each Base-derived class having to explicitly calling it) with an implemented template Clone function, this would be the ideal solution.
The problem with the third method (Foo::SetMember3) is that I'd need a template accessor for Foo. This may not always be possible, especially because of how virtual template methods are not allowed in non-template classes (Foo cannot be a template itself), which is a functionality that might be required.
My questions are:
Are these the only options I have?
Is there a better, more elegant solution to this problem that I'm missing?
Is there any way to create a base Cloneable class and derive Base from it, and have cloning automagically happen for DerivedType::Clone()?
Here's a more or less robust Clonable class that can be inherited to any depth. It uses CRTP and Alecsandrescu-style interleaving inheritance pattern.
#include <iostream>
// set up a little named template parameters rig
template <class X> struct Parent{};
template <class X> struct Self{};
template<class A, class B> struct ParentChild;
// can use ...< Parent<X>, Self<Y> >...
template<class A, class B> struct ParentChild< Parent<A>, Self<B> >
{
typedef A parent_type;
typedef B child_type;
};
// or ...< Self<Y>, Parent<X> >
template<class A, class B> struct ParentChild< Self<B>, Parent<A> >
{
typedef A parent_type;
typedef B child_type;
};
// nothing, really
struct Nada
{
// except the virtual dtor! Everything clonable will inherit from here.
virtual ~Nada() {}
};
// The Clonable template. Accepts two parameters:
// the child class (as in CRTP), and the parent class (one to inherit from)
// In any order.
template <class A, class B = Parent<Nada> > class Clonable :
public ParentChild<A,B>::parent_type
{
public:
// a nice name to refer to in the child class, instead of Clonable<A,B>
typedef Clonable Parent;
// this is our child class
typedef typename ParentChild<A,B>::child_type child_type;
// This is the clone() function returning the cloned object
// Non-virtual, because the compiler has trouble with covariant return
// type here. We have to implemens something similar, by having non-virtual
// that returns the covariant type calling virtual that returns the
// base type, and some cast.
child_type* clone()
{
return static_cast<child_type*>(private_clone());
}
// forward some constructor, C++11 style
template<typename... Args> Clonable(Args&&... args):
ParentChild<A,B>::parent_type(args...) {}
private:
// this is the main virtual clone function
// allocates the new child_type object and copies itself
// with the copy constructor
virtual Nada* private_clone()
{
// we *know* we're the child_type object
child_type* me = static_cast<child_type*>(this);
return new child_type(*me);
};
};
// Test drive and usage example
class Foo : public Clonable < Self<Foo> >
{
public:
Foo (int) { std::cout << "Foo::Foo(int)\n"; }
Foo (double, char) { std::cout << "Foo::Foo(double, char)\n"; }
Foo (const Foo&) { std::cout << "Foo::Foo(Foo&)\n"; }
};
class Bar : public Clonable < Self<Bar>, Parent<Foo> >
{
public:
// cannot say Bar (int i) : Foo(i), unfortunately, because Foo is not
// our immediate parent
// have to use the Parent alias
Bar (int i) : Parent(i)
{ std::cout << "Bar::Bar(int)\n"; }
Bar (double a, char b) : Parent(a, b)
{ std::cout << "Bar::Bar(double, char)\n"; }
Bar (const Bar& b) : Parent(b)
{ std::cout << "Bar::Bar(Bar&)\n"; }
~Bar() { std::cout << "Bar::~Bar()\n"; }
};
int main ()
{
Foo* foo1 = new Bar (123);
Foo* foo2 = foo1->clone(); // this is really a Bar
delete foo1;
delete foo2;
}
For 2nd method, you can use CRTP and you won't need to write clone method in every derived class:
struct Base {
virtual ~Base() {}
virtual Base *clone() const = 0;
};
template <typename Derived>
struct CloneableBase : public Base {
virtual Base *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
struct Derived: CloneableBase<Derived> {};
My problem is the following:
int main()
{
Base* derivedobject = new Derived1();
derivedobject->GetProperties()-> ???
return 0;
}
//********************
// BaseClass.h
//********************
struct PropertyStruct
{
int x;
};
class Base
{
public:
Base();
~Base();
virtual PropertyStruct GetProperties() = 0;
private:
};
//********************
// DerivedClass1.h
//********************
struct PropertyStruct
{
int y;
};
class Derived1 : public Base
{
public:
Derived1();
~Derived1();
PropertyStruct GetProperties() { return myOwnDifferentProperties; };
private:
};
//********************
// DerivedClass2.h
//********************
struct PropertyStruct
{
float z;
};
class Derived2 : public Base
{
public:
Derived2();
~Derived2();
PropertyStruct GetProperties() { return myOwnDifferentProperties };
private:
};
If I do it like that I'm going to get an error saying that PropertyStruct is a redefinition. If I use a namespace or rename the struct inside the derived class I am then going to get an error telling me that the return type is not the same as defined by Base.
If I define the virtual functions return type as a pointer it compiles, though the next problem when accessing the function "GetProperties" from the main method (in this example) the base object does not know what variables are inside the struct of the derived class.
Is there any way I can realize this ?
That I can get the different properties of each derived object but using the base class object ?
As others have mentioned, there are ways to achieve your goals here but ultimately you will find yourself writing code like the following:
Base * object = ...;
if object is Derived1 then
get Property1 and do something with it
else if object is Derived2 then
get Property2 and do something with it
This is an anti-pattern in object-oriented programming. You already have a class hierarchy to represent the differences between the various derived types. Rather than extracting the data from your objects and processing it externally, consider adding a virtual function to the base class and letting the derived classes do the processing.
class Base
{
public:
virtual void DoSomething() = 0;
};
class Derived1 : Base
{
public:
void DoSomething()
{
// use myOwnDifferentProperties as necessary
}
private:
PropertyStruct myOwnDifferentProperties;
};
If it's not appropriate to put the required processing in the derived classes (i.e. if it would introduce unwanted responsibilities) then you may want to consider the Visitor Pattern as a way to extend the functionality of your hierarchy.
Since template functions cannot be virtual you can use hierarchy of your properties. It's only one way, no other ways. For get elements of derived Properties you should use virtual getter functions.
struct BaseProp
{
virtual ~BaseProp() { }
virtual boost::any getProperty() const = 0;
};
struct PropertyStruct : BaseProp
{
boost::any getProperty() const { return x; }
private:
int x;
};
struct PropertyStruct2 : BaseProp
{
boost::any getProperty() const { return y; }
private:
float y;
};
class Base
{
public:
virtual std::shared_ptr<BaseProp> GetProperties() const = 0;
virtual ~Base() { }
}
class Derived
{
public:
std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct(); }
};
class Derived2
{
public:
std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct2(); }
};
You can use template class to do that:
struct PropertyStruct1 {
float f;
};
struct PropertyStruct2 {
int i;
};
template<class T>
class A{
public:
T GetProperties() {return mProps;}
private:
T mProps;
};
int main (int argc, const char * argv[]) {
A<PropertyStruct1> a1;
int f = a1.GetProperties().f;
A<PropertyStruct2> a2;
int i = a2.GetProperties().i;
return 0;
}