I have programmed several windows for an application that all inherit Gtkmm::Window. At this point, I would like to automate the process. Right now, the following structure stands out:
class MyWindow : public Gtk::Window
{
public:
MyWindow();
virtual ~MyWindow();
//...
private:
void registerLayouts(); // Adds layouts to the window.
void registerWidgets(); // Adds widgets to the layouts.
//...
};
And the constructor:
MyWindow::MyWindow()
{
registerLayouts(); // Cannot be virtual: in constructor.
registerWidgets(); // Cannot be virtual: in constructor.
//...
}
So the problem is that all of this has to be done manually (i.e. copy/pasted) every time a new window has to be programmed because registerLayouts() and registerWidgets() are called at construction and hence cannot be virtual.
Ideally, I would have a base class that I could inherit from which would give me the option of overriding the two methods and would take care of the rest: it would call the two methods at an appropriate location.
The thing is, I have not found where this appropriate location could be. I have look at different signal handlers, but there seem to be none for this.
Do you have an idea of how I could do this?
MFC has the CDialog::OnInitDialog() that performs something similar to what I need.
You could delegate the work to a separate class:
class MyWindow : public Gtk::Window
{
//public: *** EDIT ***
protected:
template <typename LayoutManager>
MyWindow(LayoutManager const& lm)
{
lm.registerLayouts(this);
lm.registerWidgets(this);
}
};
class SubWindow : public MyWindow
{
class LM { /* ... */ };
public:
SubWindow() : MyWindow(LM()) { }
};
(Edited: The improved pattern hides away from public the layout managers of sub classes...)
Alternatively, the whole class as template (possibly superior to above):
template <typename LayoutManager>
class MyWindow : public Gtk::Window
{
public:
MyWindow()
{
LayoutManager lm(*this);
lm.registerLayouts();
lm.registerWidgets();
}
};
class SpecificLayoutManager { /* ... */ };
using SpecificWindow = MyWindow<SpecificLayoutManager>;
If you need the layout manager for cleaning up as well (not familiar with GTK myself...):
template <typename LayoutManager>
class MyWindow : public Gtk::Window
{
LayoutManager lm;
public:
MyWindow() : lm(*this)
{
lm.registerLayouts();
lm.registerWidgets();
}
virtual ~MyWindow()
{
// still access to lm...
}
};
Important side note: In all variants we do not yet have a fully constructed derived class – casting to the latter within the layout managers thus is not legal (experimented with curiously recurring template pattern, but dropped the idea for exactly the same reason: needed to cast to derived in constructor of base as well).
Edit in response to comments: A sample on how you could manage additional members of a subclass (using third variant above, the template class one with the layout manager member; lm member now needs to be protected):
class SubWindowLayoutManager
{
template <typename>
friend class MyWindow;
friend class SubWindow;
int someMember;
void registerLayouts() { }
void registerWidgets() { }
};
class SubWindow : public MyWindow<SubWindowLayoutManager>
{
void doSomething()
{
lm.someMember = 77;
}
};
Additionally a new variant entirely without templates:
class MyWindow : public Gtk::Window
{
protected:
class LayoutManager
{
public:
virtual void registerLayouts(MyWindow* parent) = 0;
virtual void registerWidgets(MyWindow* parent) = 0;
};
std::unique_ptr<LayoutManager> lm;
MyWindow(std::unique_ptr<LayoutManager> lm)
: lm(std::move(lm))
{
this->lm->registerLayouts(this);
this->lm->registerWidgets(this);
}
};
class SubWindow : public MyWindow
{
class LM : public LayoutManager
{
public:
void registerLayouts(MyWindow* parent) override { }
void registerWidgets(MyWindow* parent) override { }
int someMember;
};
// convenience access function:
inline LM& lm()
{
return *static_cast<LM*>(MyWindow::lm.get());
}
public:
SubWindow() : MyWindow(std::make_unique<LM>()) { }
void doSomething()
{
//static_cast<LM*>(lm.get())->someMember = 77;
lm().someMember = 77;
}
};
Related
I have class hierarchy as shown below. It's a simplified version of actual code.
class Base
{
public :
// user_define_type is a output parameter
virtual void Fill(user_define_type);
}
class A : public Base
{
public :
void Fill(user_define_type) override;
}
class B : public Base
{
public :
void Fill(user_define_type) override;
}
I am overriding Fill() method as I need different formatting in both derived classes. Now I have to write one more class deriving from "Base" as it has common functionality. Now my problem is that new class will have to implement Fill() that will operate on different user defined type. As I am returning base class pointer from factory so new Fill() has to be virtual in base but that means I have to add it's definition in older classes "A" and "B" and throw not supported exception from them. This is not a good design. Any better design you guys can suggest ? Thanks in advance.
I believe you need to create a common base class for your user_defined_types in order to achieve this. I also think this could be a good place to use the strategy pattern.
Basically, you create
class user_defined_type_base
{
...
}
class user_defined_type_derived : public user_defined_type_base
{
...
}
class DoSomething
{
private:
DoSomethingStrategy *strategy;
public:
DoSomething(DoSomethingStrategy *strategy) { this->strategy = strategy; }
void Fill(user_defined_type_base *type) { this->strategy->Fill(type); }
}
class DoSomethingStrategy
{
public:
virtual void Fill(user_defined_type_base *obj) = 0;
}
class DoSomethingStrategyA : public DoSomethingStrategy
{
public:
void Fill(user_defined_type_base *obj)
{
...
}
}
class DoSomethingStrategyB : public DoSomethingStrategy
{
public:
void Fill(user_defined_type_base *obj)
{
...
}
}
class DoSomethingStrategyC : public DoSomethingStrategy
{
public:
void Fill(user_defined_type_base *obj)
{
...
}
}
void main()
{
DoSomethingStrategy *strategy = new DoSomethingStragegyA();
DoSomething *dosomething = new DoSomething(strategy);
user_defined_type_base *type = new user_defined_type_base();
dosomething->Fill(type);
DoSomethingStrategy *strategyC = new DoSomethingStragegyC();
DoSomething *dosomethingC = new DoSomething(strategyC);
user_defined_type_base *typeC = new user_defined_type_derived();
dosomethingC->Fill(typeC);
}
I'm currently creating a game in SFML. To put it simply, I have an Object class that has all the common features for all objects. Player and Enemy class inherit from Object. There is also an ObjectManager that has a list of all Object and updates and draws them etc.
// using SFML shapes
class Player : public Object
{
public:
sf::CircleShape playerShape;
};
class Enemy : public Object
{
public:
sf::Sprite enemyShape;
};
class Object
{
public:
void move(...) { // move the shape, but the shapes are only found in the derived }
void draw(...) { // same problem as above, etc... }
};
class ObjectManager
{
private:
std::map<int, std::shared_ptr<Object>> gameObjectMap; // id, object
public:
void updateAll(...) {
// loop over all objects and update them
for (auto itr = gameObjectMap.begin(); itr != gameObjectMap.end(); ++itr) {
itr->second->move(...);
itr->second->draw(...);
}
}
};
Above you can see that Object::move() cannot be used because Object does not know about the SFML shapes in the derived classes. Therefore you could make the function Object::move() pure virtual but this means that you'd need to write implementations in the derived classes for any shape specific function that you need to use, this also includes any attributes about the shape, such as its position sf::Shape::getPosition(), etc. So this approach does not scale well.
An alternative that I thought about would be to have the Object class as a class template
template<typename T>
class Object
{
protected:
T object;
public:
void move(...) { object.move(...); }
T getObject() { return object; }
};
class Player : public Object<sf::CircleShape>
{ ... };
However this means that ObjectManager now must hold class templates Object in the map, and I'm not sure how that would work?
What's the best way to handle this situation?
how about this:
class Object
{
virtual auto move() -> void = 0;
};
template <class Shape>
class Shape_object : Object
{
Shape shape;
auto move() -> void override
{
// implementation
}
};
// you can have specializations for each shape type
// if you can't use the generic one
class Player : public Shape_object<sf::CircleShape>
{
//
};
class Enemy : public Shape_object<sf::Sprite>
{
//
};
template<typename T>
class Object {
// ...
};
If you really consider using a template class, you should use the CRTP (aka Static Polymorphism):
template<typename Derived>
class Object {
public:
/* virtual */ auto move() -> void {
// ^^^^^^^^^^^^^ Hooray! No more vtable \o/ (but wait ...)
static_cast<Derived*>(this)->doMove(); // Fails to compile, if
// Derived isn't inheriting from
// Object<Derived> or Derived
// doesn't implement doMove().
};
};
The drawback of that pattern is that everything must be resolved at compile time. Runtime injections of interface implementations (e.g. via plugins) won't work with that pattern well.
You could leave a thin layer though to make virtual destruction and such work properly:
struct ObjectBase {
virtual ~ObjectBase() {} // << that's enough
};
template<typename Derived>
class Object : public ObjectBase {
// ...
}
Let a class hierarchy :
class Base { virtual ~Base() throw(); };
class DerivedA : public Base { };
class DerivedB : public Base { };
I would like to have some code specific to each of these derived classes. However that code also being specific to the application that makes use of this class hierarchy, I do not want to embbed this derived-class-specific code into these derived classes. To avoid doing so, I thought about writing free functions :
void DerivedASpecificWork( DerivedA da );
void DerivedBSpecificWork( DerivedB db );
However, when given an instance of a derived class through a reference/pointer to a Base, I do not have access to the actual type of the instance, and thus cannot call the proper Derived*SpecificWork() function.
I would like to know if there is nome kind of design pattern that would allow me to call a derived-class-specific function without knowing the actual type of the instance, i.e having the same mechanism as virtual functions provide, but without having these virtual functions that would require me to embbed application-specific code into that class hierarchy.
Actually, why I want to do that is to provide informations about an exception that occured within a natively implemented function called by a Lua script. Each exception carrying its own set of information, the way I want to represent the error within the script depends on the type of the exception. I could create a pure virtual method in the base class that would be implemented by derived classes, but this would require me to embbed Lua-related code into my exception hierarchy, which I do not want to do since the Lua is specific to one of the application using that exception hierarchy.
Also I cannot use C++11.
Thank you.
May be Brigde pattern can help you.
This pattern can be used when you want to avoid a permanent binding between an abstraction and it's implementation.
(I don't see your comment about your restriction in using c++11, but you can remove std::unique_ptr, std::move and override keyword)
class AppSpecificImp
{
public:
virtual void DoWork() = 0;
};
class Base
{
public:
virtual ~Base() throw();
virtual DoWork() = 0;
};
class DerivedA : public Base
{
public:
DerivedA(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedA specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
class DerivedB : public Base
{
public:
DerivedB(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedB specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
Edit to show Visitor pattern usage:
With visitor pattern you can do what you want but with more Effort.
class Visitor
{
public:
virtual void VisitDerivedA(DerivedA* object) = 0;
virtual void VisitDerivedB(DerivedB* object) = 0;
};
class Base
{
public:
virtual void Visit(Visitor* visitor) = 0;
};
class DerivedA : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedA(this);
}
};
class DerivedB : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedB(this);
}
};
class AppSpecificVisitor : public Visitor
{
public:
void VisitDerivedA(DerivedA* object)
{
// Do any work related to DerivedA class
}
void VisitDerivedB(DerivedB* object)
{
// Do any work related to DerivedB class
}
}
int main()
{
AppSpecificVisitor myVisitor;
Base* myBase = // any class in your hierarchy
myBase->Visit(&myVisitor);
}
As I said in comments with Visitor pattern you can add new functionally without changing the main hierarchy(Base->Derived types). You just define a new visitor implementation and write your logic for every class in main hierarchy. In your example you can pack app specific logic in an object and reference that in your derived objects that is an easier approach.
Why not using a new set of hierarchy for application specific implementation ?
class AppBase
{
public:
virtual ~AppBase() throw();
virtual void work_with_app() = 0;
};
class Base
{
public:
Base(AppBase& app) : m_app(app) {}
virtual ~Base() throw();
protected:
AppBase& m_app;
};
class DerivedA : public Base { DerivedA(AppBase& app) : Base(app) {} };
class DerivedB : public Base { DerivedA(AppBase& app) : Base(app) {} };
// Application specific implementation :
class AppLuaSpecific : public AppBase
{
public:
void work_with_app() { /* Lua app specific */ }
};
This way, your 1st hierarchy : Base, DerivedA, DerivedB can live without knowing anything about the app specific code implemented in AppLuaSpecific.
You can implement your own app-specific dispatch as follows (check it live on Coliru):
#include <iostream>
#include <typeinfo>
struct Base { virtual ~Base() {} };
struct DerivedA : public Base { };
struct DerivedB : public Base { };
namespace AppSpecific
{
template<class F>
void dispatch(const Base& b)
{
const std::type_info& t = typeid(b);
if ( t == typeid(DerivedA) )
F::doit(static_cast<const DerivedA&>(b));
else if ( t == typeid(DerivedB) )
F::doit(static_cast<const DerivedB&>(b));
}
struct Foo
{
static void doit(const DerivedA& da) { std::cout << "Foo(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Foo(DerivedB)\n"; }
};
struct Bar
{
static void doit(const DerivedA& da) { std::cout << "Bar(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Bar(DerivedB)\n"; }
};
} // namespace AppSpecific
int main()
{
DerivedA da;
DerivedB db;
Base& b1 = da;
Base& b2 = db;
AppSpecific::dispatch<AppSpecific::Foo>(b1);
AppSpecific::dispatch<AppSpecific::Foo>(b2);
AppSpecific::dispatch<AppSpecific::Bar>(b1);
AppSpecific::dispatch<AppSpecific::Bar>(b2);
}
I am trying to refactor and rewrite some parts of a legacy library. This library has base classes with same variable names repeatedly declared and used in derived classes (caused by copy/paste programming). For example I have:
class MyBaseClass
{
public:
int m_nVar;
protected:
virtual void MyFunc()
{
m_nVar++;
}
public:
MyBaseClass()
{
m_nVar = 1;
}
};
class MyDerivedClass : public MyBaseClass
{
public:
int m_nVar;
protected:
virtual void MyFunc()
{
m_nVar++;
}
public:
MyDerivedClass ()
{
m_nVar = 2;
}
};
This situation causes me problems because I need to move some functionality I need to a more general base class so that MyBaseClass can be derived from it.
class MyNewBaseClass
{
public:
int m_nVar;
protected:
virtual void MyFunc()
{
m_nVar++;
}
public:
MyNewBaseClass()
{
}
};
class MyBaseClass : public MyNewBaseClass
{
public:
MyBaseClass()
{
m_nVar = 1;
}
};
class MyDerivedClass : public MyBaseClass
{
public:
int m_nVar;//this causes me problems, I need to get notifications on occurrences of such situations
public:
MyDerivedClass ()
{
m_nVar = 2; //this assignments has no effect on MyNewBaseClass::m_nVar
}
};
After I make my modifications MyFunc() in a MyDerivedClass instance does not work as the original code (first run on original causes m_nVar = 3, but in my modified code it becomes m_nVar = 2).
I need some kind of compiler error or warning to notify me of all occurrences of such situations or any other solutions to accomplish what I need.
What do you suggest which works in Visual Studio (VC++)?
I have a MainWindow class
class MainWindow : public QMainWindow
{
customClass * obj;
public:
void foo(bool);
}
Here is my customClass:
class customClass
{
void foo1(bool);
}
Now, I want to call foo() method in foo1().
How to do that?
You can make the constructor of your customClass take a pointer to a MainWindow which it stores in a member variable for later use.
class customClass
{
public:
customClass(MainWindow* mainWindow)
: mainWindow_(mainWindow)
{
}
void foo1(bool b) {
mainWindow_->foo(b);
}
private:
MainWindow* mainWindow_;
}
One of way - using of dependency injection pattern: link
struct A;
struct B
{
B( A& a );
void foo1()
{
m_a.foo();
}
private:
A& m_a;
}
struct A
{
void foo(){}
B m_b;
}
You can make your MainWindow implements singleton pattern (if it's applicable to your design), then you can directly get an instance from any place you like.