C++ Reusable module class design - c++

I have many, many modules that can benefit from using the exact same design pattern and share common classes. On the individual component level, everything makes sense, classes can easily be extended. But when I try to tie them together into a common module object, it seems like a pattern that polymorphism wasn't meant for, and I am missing the right pattern or design.
Starting out with all the base classes, which all other classes will extend from. The Module is the glue and the problem. Module will contain methods that prevent code duplication, such as AddComponent.
// A physical interface (Ethernet, Bluetooth, etc)
class Interface {};
// A basic component
class Component {};
// An std::map wrapper for managing Components
class ComponentManager {};
// A place to store data
class Database {};
// A module to tie all things together
class Module {
public:
Interface interface;
ComponentManager manager;
Database db;
void AddComponent(Component& c) {
manager.AddComponent(c);
db.InsertComponent(c);
}
};
Everything is fine until we want to extend all or most of the classes and the Module as well.
class EthInterface : public Interface {}; // cool
class UdpClientComponent : public Component {}; // cool
class UdpClientDatabase : public Database {}; // cool
//class UdpClientComponentManager : public ComponentManager {}; // 90% of the time won't need it
class UdpClientModule : public Module {
public:
EthInterface interface; // how to get an EthInterface instead of Interface?
UdpClientDatabase db; // how to get a UdpClientDatabase instead of Database?
};
I am trying to understand what pattern or design or what to use here. I think templates might not be the right solution because I've simplified this example, and don't think templates with 5 or 6 Ts are good design. I don't really get how to design this using ptrs because then I am feeding the extended Module ptrs from the outside, and I want this to be self contained, so that people can just write UdpClientModule module and they get batteries included, so to speak.

This might be a kick in the dark, but maybe it will send you searching in a different direction... You could use templates, redefining Module to look something like this:
template <class IFC, class COMP, class CM, class DB> class Module {
public:
IFC interface;
CM manager;
DB db;
void AddComponent(COMP& c) {
manager.AddComponent(c);
db.InsertComponent(c);
}
};
But if you go that way you should make sure that IFC, COMP, CM and DB are derived from Interface, Component, ComponentManager and Database and for that you need concepts. I don't know about you, but that is a bit over my head, so I would go a different way:
class Module {
public:
Module(Interface &ifc, Database &_db) :
interface(ifc),
manager(), db(_db) {
}
void AddComponent(Component& c) {
manager.AddComponent(c);
db.InsertComponent(c);
}
private:
Interface &interface;
ComponentManager manager;
Database &db;
};
class UdpClientModule : public Module {
public:
UdpClientModule() :
Module(ethInterface, udpClientDb),
ethInterface(),
udpClientDb() {
}
private:
EthInterface ethInterface;
UdpClientDatabase udpClientdb;
};
It's still clumsy, but it at least gets you some of the way to where (I assume) you want to get.

Interfaces depends from abstraction, you want to depend from concrete types and there where your design flaw. Keep the interface to do the "interface" and leave the concrete classes dealing with the concrete types.
class Module {
public:
virtual ~Module() = default;
void AddComponent(Component& c) {
manager().AddComponent(c);
db().InsertComponent(c);
}
virtual Interface& interface() = 0;
virtual ComponentManager& manager() = 0;
virtual Database& db() = 0;
};
class UdpClientModule : public Module {
public:
Interface& interface() override { return ethInterface; }
ComponentManager& manager() override { return udcClienddb; }
Database& db() override { return manager; }
void specialUdpMethod() const { /*...*/}
private:
EthInterface ethInterface;
UdpClientDatabase udpClientdb;
ComponentManager manager;
};
In this case you're stating every module must provide an interface, e component manager and a db. If you have more relaxed constraint you could move the dependencies to a dependency injection solution and use pointer instead.

Related

Abstract Factory in C++

I'm trying to understand the abstract factory pattern, here is my first approximation:
#include <iostream>
using namespace std;
class Soldier
{
public:
virtual void shoot()=0;
};
class Archer: public Soldier
{
public:
void shoot(){
cout<<"Archer shoot"<<endl;
}
};
class Rider: public Soldier
{
public:
void shoot(){
cout<<"Rider shoot"<<endl;
}
};
class AbstractFactory
{
public:
virtual Soldier* createArcher()=0;
virtual Soldier* createRider()=0;
};
class OrcFactory: public AbstractFactory
{
Soldier* createArcher()
{
return new Archer();
};
Soldier* createRider()
{
return new Rider();
};
};
class HumanFactory: public AbstractFactory
{
Soldier* createArcher()
{
return new Archer();
};
Soldier* createRider()
{
return new Rider();
};
};
class Game
{
public:
AbstractFactory* factory;
Game(AbstractFactory* factory):factory(factory){};
};
int main()
{
Game* game = new Game(new HumanFactory);
Archer* HumanArcher = static_cast <Archer*>(game->factory->createArcher());
Rider* humanRider = static_cast <Rider*>(game->factory->createRider());
HumanArcher->shoot();
humanRider->shoot();
return 0;
}
This is what I want to reproduce:
I have experience in programing but I'm newbie with patterns, not sure if this is the optimal solution or even if it's a good solution.
I'm reading about game engine architecture, but I'm stuck in this, not by errors, just doubt about the right solution for this exercise. The book has basic examples but not enough to understand it at all.
That's not exactly what makes an abstract factory. In your case, you would need a structure like this (the diagram ended up a bit too big, click the image to see it at its original resolution):
The idea is that you have a family of abstract classes or interfaces (here the units, archer, rider, etc.) and a family of concrete implementations for each type of factory (implementations for humans, implementations for orcs, etc.). The game uses only the abstract factory interface and does not need to care which are the actual types, while each implementation only needs to provide its own behaviour, allowing for easy extension.
As a side note, I used covariant return types in the diagram because C++ supports it (as opposed to, for example, C#) and it seems to make sense in this case (e.g. the method makeArcher in the base factory interface SoldierFactory is declared to return an Archer object, but the same method in OrcSoldierFactory returns a OrcArcher), but that is not strictly required by the pattern.

Contravariant types and extensibility

I'm writing a C++ library for optimization, and I've encountered a curious issue with contra-variant types.
So, I define a hierarchy of "functions", based on what information they can compute.
class Function {
public:
double value()=0;
}
class DifferentiableFunction : public Function {
public:
const double* gradient()=0;
}
class TwiceDifferentiableFunction : public DifferentiableFunction {
public:
const double* hessian()=0;
}
Which is all well and good, but now I want to define interfaces for the optimizers. For example, some optimizers require gradient information, or hessian information in order to optimize, and some don't. So the types of the optimizers are contravariant to the types of the functions.
class HessianOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : public HessianOptimizer {
public:
set_function(DifferentiableFunction* f)=0;
}
class Optimizer: public GradientOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
Which I suppose makes sense from a type theoretic perspective, but the thing that is weird about it is that usually when people want to extend code, they will inherit the already existing classes. So for example, if someone else was using this library, and they wanted to create a new type of optimizer that requires more information than the hessian, they might create a class like
class ThriceDifferentiableFunction: public TwiceDifferentiableFunction }
public:
const double* thirdderivative()=0;
}
But then to create the corresponding optimizer class, we would have to make HessianOptimizer extend ThirdOrderOptimizer. But the library user would have to modify the library to do so! So while we can add on the ThriceDifferentiableFunction without having to modify the library, it seems like the contravariant types lose this property. This seems to just be an artifact of the fact the classes declare their parent types rather than their children types.
But how are you supposed to deal with this? Is there any way to do it nicely?
Since they're just interfaces, you don't have to be afraid of multiple inheritance with them. Why not make the optimiser types siblings instead of descendants?
class OptimizerBase
{
// Common stuff goes here
};
class HessianOptimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : virtual public OptimizerBase {
public:
virtual set_function(DifferentiableFunction* f)=0;
}
class Optimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
// impl
class MyGradientOptimizer : virtual public GradientOptimizer, virtual public HessianOptimizer
{
// ...
};

Whats best way to go from a String to Type (C++)

I want to be able to specifiy a type in as a string and create that type in C++. I know C++ doesn't support that directly but whats the best way to approach this?
I currently have an xml that contains information but I want to expand that to include components.
<entity>
<component>ComponentA</component>
<component>ComponentB</component>
</entity>
I have a generic factory that takes in these xml's and builds up the entities. I want to be able to avoid if("componentA") { new ComponentA; } in favour of something more generic. Primarily as the components will be defined by the client and the factory is not.
I thought that components could register themselves with the factory and store a map, but that would require holding a copy of all the components which I'd like to avoid.
I crossplatform solution would be preferable.
AFAIK, at least with general C++, there's no implicit way to create a class using just a string. However, there is another mechanism I have used in the past.
Firstly, you define the notion of a component:
class Component /* or IComponent if you're feeling adventurous - we may not have interfaces in C++, but dammit we like 'em! */
{
protected:
Component() { };
public:
virtual ~Component() = 0 { };
}; // eo class Component
And a notion of a some kind of creator:
class ComponentCreator
{
protected:
Component() { };
public:
virtual ~ComponentCreator() = 0 { };
virtual Component* create() const = 0; // Might want to use smart-pointers here - this is for illustrative purposes only.
}; // eo class ComponentCreator
Ok, we have the basics now we need a factory that can have these creators registered against it:
class Factory
{
private:
std::map<std::string, ComponentCreator*> _creators;
public:
Factory() : _creators(new std::map<std::string, ComponentCreator*>();
{
};
~Factory()
{
// cleanup of _creators ommited.
};
// call to register a creator
void register(const std::string& name, ComponentCreator* creator)
{
// normally you'd put checks to see if it exists etc.
_creators[name] = creator;
}; // eo register
// call to create an instance
Component* create(const std::string& name)
{
std::map<std::string, ComponentCreator*>::const_iterator cit(_creators.find(name));
if(cit != _creators.end())
return cit->create();
else
return NULL; // or nullptr
}; // eo create
}; // eo class Factory
Declare your classes thusly (I will do just one):
class ComponentA : public Component { /* implementation */ };
And don't forget the creator:
class ComponentCreatorForA : public ComponentCreator
{
public:
virtual Component* create() const { return new ComponentA(); };
}; // eo class ComponentCreatorForA
During initialisation of your program, you register component creators:
factory.register("componentA", new ComponentCreatorForA());
factory.register("componentB", new ComponentCreatorForB());
And later on, we can then create components by name:
Component* component = factory.create("componentA");
Notes:
This approach assumes components are known at compile-time. If not one could introduce a plugin-architecture so that additional DLLs can register their components via the factory on start-up so you could make it extensible without having to re-deploy everything.
In the real world we'd use smart pointers of some such, and typedef a lot of that stuff away to make it easier on typing!
You have to store meta-information about your component classes. A possible solution might use templates:
// the component interface
class BaseComponent {...}
// structure containing meta-information
template<typename ComponentType>
struct tComponentMeta {
typedef ComponentType type;
std::string componentTypeName;
tComponentMeta() : componentTypeName("no valid component type") {}
}
// providing run time type information
// (optional, but i like it if the component know about their type
template<typename ComponentType>
class TComponent : public BaseComponent
{
tComponentMeta<ComponentType> metaInfo;
TComponent(const std::string& uniqueTypeName) {...};
}
class ConcreteComponent : public TComponent<ConcreteComponent>
{
...
}
Now the client has to define the specialized tComponentMeta for the ConcreteComponent type. This can be achieved by adding the following code after the class declaration of ConcreteComponent:
template <>
struct tComponentMeta {
typedef ConcreteComponent type
tComponentMeta() : componentTypeName("ConcreteComponent") {}
}
So if you clients define the template specialization for the components you can provide them with a generic factory that has a template method of the following type, that also has to be invoked by the client designing the component:
...
template<typename ComponentType>
registerComponentType() {
tComponentMeta<ComponentType> metaInfo;
nameToMetaMap.put(metaInfo.name, metaInfo)
}
with these building blocks you can generate components in a generic way by forcing the client to provide tComponentMeta specializations of their components and register the component-type at your generic factory.
This code has not been tested by myself so you can assume that there are some syntax errors but I hope the idea is clear.
Due to the nature of templates that approach shall also work in a plug-in architecture that uses DLLs.

In C++, how can I create two interfaces for a class?

For example, when creating a class library, I would like to specify an internal API and a public API for each classes, so I can hide some details from the user. The internal API would be used by other classes in the library, and the public API would be used by the library user.
Is it possible?
In C++, interface could mean many things. It could mean pure virtual functions that you implement in the derived classes, as in the following example,
class Interface
{
public:
virtual void f() = 0 ;
};
class Implementation : public Interface
{
public:
virtual void f() {}
};
--
Or it could mean just public functions in your class:
class A
{
public:
void f() {} //public function - an interface that the outside world can
//use to talk to your class.
};
You can use either of these and can make use of access-specifiers ( public, protected, private) to make your interfaces public or internal/private!
Kind of.
Some libraries use friend classes/functions for this. Each class declares other classes as friends if they need access to more than the "public" interface:
class Car {
friend class Mechanic;
private:
Engine engine;
};
class Mechanic {
// something involving Car::engine...
};
It's not very pretty, but it works.
Another approach that might work for you is the pimpl (pointer-to-implementation) idiom:
class CarImpl; // declaration only
class Car {
private:
CarImpl *impl;
public:
CarImpl *getImpl(); // doesn't strictly belong in the pimpl pattern
// methods that simply call the corresponding methods on impl
};
The internal interface can be accessed through a getImpl() call. You would put the CarImpl declaration in a header file that is clearly marked as internal, so clients won't access it. For example, you could put such headers in a subdirectory called internal.
The obvious drawback is that the Car class has a bunch of trivial methods that you have to implement.
A third approach, that I do not recommend, is inheritance:
class Car {
public:
virtual void start() = 0;
static Car *create();
};
And in an internal header:
class CarImpl : public Car {
public:
virtual void start();
};
The Car class only exposes the public interface; to get access to the internal interface, internal code needs to do a downcast to CarImpl. This is ugly.
You can use many tricks to grant friendship or an "extended" interface to a given few, however it is soon cumbersome.
The simplest way to separate the external interface from the internal interface... is to have two interfaces, thus two classes.
If you take a peek at the set of Design Patterns proposed by the GoF, you'll notice the Proxy pattern.
You can use this by not exposing the class to the exterior of your library, but instead exposing a Proxy, in which you wrap the class, and which only exposes a subset of its interface.
class MyClass
{
public:
void foo();
void bar();
void printDebugInfo();
void test();
};
class MyClassProxy
{
public:
MyClassProxy(std::unique_ptr<MyClass> ptr): _ptr(ptr) {}
void foo() { _ptr->foo(); }
void bar() { _ptr->bar(); }
private:
std::unique_ptr<MyClass> _ptr;
};
I personally find this design rather clean. No down-casting, No subtle inheritance trick, No friendship list longer than my arm.
I'm not quite sure what you're asking, but if you have an abstract class defined:
class Loggable { ... };
You can inherit from it privately, like this:
class User : private Loggable { ... };
The class User now has the members of Loggable, but they are private.
Please see the C++ FAQ lite.
There is a number of ways to approach this. One is runtime polymorphism:
struct widget {
virtual debug_info diagnose() = 0;
virtual void draw() = 0;
};
struct window {
virtual void draw() = 0;
};
struct view : public window, public widget {
void draw();
debug_info diagnose(); // internal
};
Or with compile-time polymorphism:
struct view {
void draw();
debug_info diagnose(); // internal
};
template<class W>
void do_it(W window)
{
widget.draw();
}
template<class W>
void diagnose_it(W widget)
{
debug_info d = widget.diagnose();
}
Another approach is to expose private members to specific functions or classes:
struct widget {
virtual void draw() = 0;
};
struct view : public widget {
friend void diagnose_widget(widget w);
void draw();
private:
debug_info diagnose();
};
// internal
debug_info diagnose_widget(widget w)
{
debug_info d = w.diagnose();
}
A C++ class has 3 levels of protection: public, protected and private. Public things are accessible to everybody, protected only to descendant -- and then for themselves and not for other descendants --, private for the class and its friend.
Thus friendship is the only way to grant more than public access to a class/function which isn't a descendant, and it grants full access, which isn't always convenient.
An heavy solution which I've used with success was to write a wrapper which was a friend of the main class, and then provided additional access to its own friends (which were the only one able to construct the wrapper). I'm not really recommending it, it is tedious, but it could be useful if you have such a need.
class Main {
public:
...
private: // but wrapped
void foo();
protected:
...
private: // and not wrapped
void bar();
};
class Wrapper {
pubic:
void foo() { wrapped.foo(); }
private:
Wrapper(Main& m) : wrapped(ma) {}
Main& wrapped;
friend void qux(Main&);
};
void qux(Main& m) {
Wrapper mwrapped(m)
mwrapped.foo();
// still can't access bar
}

Registering derived classes in C++

EDIT: minor fixes (virtual Print; return mpInstance) following remarks in the answers.
I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class.
All the objects that create and use the base class objects shouldn't change the way they create or call an object, i.e. should continue calling BaseClass.Create() even when they actually create a Child class.
The Base classes know that they can be overridden, but they do not know the concrete classes that override them.
And I want the registration of all the the Child classes to be done just in one place.
Here is my implementation:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
template<typename Class>
class CRegisteredClassFactory: public CAbstractFactory
{
public:
~CRegisteredClassFactory(){};
Class* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
Class* pClass;
};
// holds info about all the classes that were registered to be overridden
class CRegisteredClasses
{
public:
bool find(const string & sClassName);
CAbstractFactory* GetFactory(const string & sClassName)
{
return mRegisteredClasses[sClassName];
}
void RegisterClass(const string & sClassName, CAbstractFactory* pConcreteFactory);
private:
map<string, CAbstractFactory* > mRegisteredClasses;
};
// Here I hold the data about all the registered classes. I hold statically one object of this class.
// in this example I register a class CChildClass, which will override the implementation of CBaseClass,
// and a class CFooChildClass which will override CFooBaseClass
class RegistrationData
{
public:
void RegisterAll()
{
mRegisteredClasses.RegisterClass("CBaseClass", & mChildClassFactory);
mRegisteredClasses.RegisterClass("CFooBaseClass", & mFooChildClassFactory);
};
CRegisteredClasses* GetRegisteredClasses(){return &mRegisteredClasses;};
private:
CRegisteredClasses mRegisteredClasses;
CRegisteredClassFactory<CChildClass> mChildClassFactory;
CRegisteredClassFactory<CFooChildClass> mFooChildClassFactory;
};
static RegistrationData StaticRegistrationData;
// and here are the base class and the child class
// in the implementation of CBaseClass::Create I check, whether it should be overridden by another class.
class CBaseClass
{
public:
static CBaseClass* Create()
{
CRegisteredClasses* pRegisteredClasses = StaticRegistrationData.GetRegisteredClasses();
if (pRegisteredClasses->find("CBaseClass"))
{
CRegisteredClassFactory<CBaseClass>* pFac =
dynamic_cast<CRegisteredClassFactory<CBaseClass>* >(pRegisteredClasses->GetFactory("CBaseClass"));
mpInstance = pFac->CreateAndGet();
}
else
{
mpInstance = new CBaseClass;
}
return mpInstance;
}
virtual void Print(){cout << "Base" << endl;};
private:
static CBaseClass* mpInstance;
};
class CChildClass : public CBaseClass
{
public:
void Print(){cout << "Child" << endl;};
private:
};
Using this implementation, when I am doing this from some other class:
StaticRegistrationData.RegisterAll();
CBaseClass* b = CBaseClass::Create();
b.Print();
I expect to get "Child" in the output.
What do you think of this design? Did I complicate things too much and it can be done easier? And is it OK that I create a template that inherits from an abstract class?
I had to use dynamic_pointer (didn't compile otherwise) - is it a hint that something is wrong?
Thank you.
This sort of pattern is fairly common. I'm not a C++ expert but in Java you see this everywhere. The dynamic cast appears to be necessary because the compiler can't tell what kind of factory you've stored in the map. To my knowledge there isn't much you can do about that with the current design. It would help to know how these objects are meant to be used. Let me give you an example of how a similar task is accomplished in Java's database library (JDBC):
The system has a DriverManager which knows about JDBC drivers. The drivers have to be registered somehow (the details aren't important); once registered whenever you ask for a database connection you get a Connection object. Normally this object will be an OracleConnection or an MSSQLConnection or something similar, but the client code only sees "Connection". To get a Statement object you say connection.prepareStatement, which returns an object of type PreparedStatement; except that it's really an OraclePreparedStatement or MSSQLPreparedStatement. This is transparent to the client because the factory for Statements is in the Connection, and the factory for Connections is in the DriverManager.
If your classes are similarly related you may want to have a function that returns a specific type of class, much like DriverManager's getConnection method returns a Connection. No casting required.
The other approach you may want to consider is using a factory that has a factory-method for each specific class you need. Then you only need one factory-factory to get an instance of the Factory. Sample (sorry if this isn't proper C++):
class CClassFactory
{
public:
virtual CBaseClass* CreateBase() { return new CBaseClass(); }
virtual CFooBaseClass* CreateFoo() { return new CFooBaseClass();}
}
class CAImplClassFactory : public CClassFactory
{
public:
virtual CBaseClass* CreateBase() { return new CAImplBaseClass(); }
virtual CFooBaseClass* CreateFoo() { return new CAImplFooBaseClass();}
}
class CBImplClassFactory : public CClassFactory // only overrides one method
{
public:
virtual CBaseClass* CreateBase() { return new CBImplBaseClass(); }
}
As for the other comments criticizing the use of inheritance: in my opinion there is no difference between an interface and public inheritance; so go ahead and use classes instead of interfaces wherever it makes sense. Pure Interfaces may be more flexible in the long run but maybe not. Without more details about your class hierarchy it's impossible to say.
Usually, base class/ derived class pattern is used when you have an interface in base class, and that interface is implemented in derived class (IS-A relationship). In your case, the base class does not seem to have any connection with derived class - it may as well be void*.
If there is no connection between base class and derived class, why do you use inheritance? What is the benefit of having a factory if factory's output cannot be used in a general way? You have
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
This is perfectly wrong. A factory has to manufacture something that can be used immediately:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory(){};
public:
CBaseClass* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
CBaseClass* pClass;
protected:
CBaseClass *create() = 0;
};
In general, you're mixing inheritance, virtual functions and templates the way they should not be mixed.
Without having read all of the code or gone into the details, it seems like you should've done the following:
make b of type CChildClass,
make CBaseClass::Print a virtual function.
Maybe I'm wrong but I didn't find any return statement in your CBaseClass::Create() method!
Personally, I think this design overuses inheritance.
"I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class." - I don't know that IS-A relationships should be that flexible.
I wonder if you'd be better off using interfaces (pure virtual classes in C++) and mixin behavior. If I were writing it in Java I'd do this:
public interface Foo
{
void doSomething();
}
public class MixinDemo implements Foo
{
private Foo mixin;
public MixinDemo(Foo f)
{
this.mixin = f;
}
public void doSomething() { this.mixin.doSomething(); }
}
Now I can change the behavior as needed by changing the Foo implementation that I pass to the MixinDemo.