I have the following interfaces
template <typename string_t>
class PluginManager
{
public:
virtual ~PluginManager() = default;
virtual Plugin<string_t>* findPlugin(string_t const&plugin_uuid) const = 0;
virtual Plugin<string_t>* loadPlugin(string_t const&plugin) = 0;
virtual void unloadPlugin(string_t const&plugin) = 0;
virtual void registerPlugin(Plugin<string_t> *plugin) = 0;
virtual void unregisterPlugin(Plugin<string_t> *plugin) = 0;
virtual void sigPluginLoaded() = 0;
};
template <typename string_t>
class Plugin
{
public:
virtual ~Plugin() = default;
virtual string_t uuid() const = 0;
virtual void setManager(PluginManager<string_t> *manager) = 0;
};
I also have two classes that implement these interfaces
class Core : public QObject, public PluginManager<QString>
{
Q_OBJECT
using string_t = QString;
using map_t = QMap<string_t, ad::Plugin<string_t>*>;
private:
Core();
public:
static Core* instance();
Plugin<string_t>* findPlugin(string_t const&plugin_uuid) const override;
Plugin<string_t>* loadPlugin(string_t const&plugin) override;
void unloadPlugin(string_t const&plugin) override;
void registerPlugin(Plugin<string_t> *plugin) override;
void unregisterPlugin(Plugin<string_t> *plugin) override;
signals:
void sigPluginLoaded();
private:
map_t __plugin_map;
static Core* __instance;
};
class SettingsApplierPlugin : public QObject, public ad::Plugin<QString>
{
Q_OBJECT
public:
SettingsApplierPlugin();
QString uuid() const override;
void setManager(ad::PluginManager<QString> *manager) override;
public slots:
void updateSettings() const;
private:
PluginManager<QString> *__plg_mgr;
};
And finally the function implementation that neccessary for this question
void Core::registerPlugin(ad::Plugin<Core::string_t> *plugin)
{
plugin->setManager(this);
__plugin_map.insert(plugin->uuid(), plugin);
emit sigPluginLoaded();
}
The problem
When I debug the code (I use VSCode with gdb 8.2.91 and Ubuntu 19.04) it behaves strangely. When I step into the plugin->setManager(this) (the plugin in this point is an instance of class SettingsApplierPlugin) the debugger shows the line of the declaration of that class and after one more step-into, it shows the line of the destructor of the Plugin class.
Notice
The image changes, when I remove the QObject class from bases of SettingsApplierPlugin and the Q_OBJECT macro from the class definition, everything works fine and debugger enters into the function correctly.
Note 1
The class SettingsApplierPlugin comes from a shared library and the class Core comes from another shared library.
Note 2
All string_ts are typedefs -> using string_t = QString.
My restrictions
I want to derive from QObject because I want to use the provided signal-slot mechanism.
The question
Can anybody explain the behavior and suggest a solution to this problem?
Related
I have two interfaces:
class FirstInterface
{
virtual int getId() const = 0;
};
class SecondInterface
{
virtual void setId(int id) = 0;
};
This is a combined interface:
class CombinedInterface : public FirstInterface, public SecondInterface
{
};
This is a concrete class of first interface:
class FirstConcrete : public FirstInterface
{
virtual int getId() const
{
return 1;
}
};
Now, this class CompleteConcrete should have the CombinedInterface but want to reuse the implementation of FirstConcrete at the same time.
class CompleteConcrete : public FirstConcrete, public SecondInterface
{
virtual void setId(int id) { }
};
// This is wrong C++
// Cannot convert from CompleteConcrete * to CombinedInterface *
// CombinedInterface * combinedInterface = new CompleteConcrete();
This is not working of course. Does anyone know a way to achieve this goal in C++ ??
Here's the virtual-inheritance based solution that I mentioned in the comments:
class FirstInterface
{
virtual int getId() const = 0;
};
class SecondInterface
{
virtual void setId(int id) = 0;
};
class CombinedInterface : virtual public FirstInterface,
virtual public SecondInterface
{
};
class FirstConcrete : virtual public FirstInterface
{
virtual int getId() const
{
return 1;
}
};
class CompleteConcrete : virtual public FirstConcrete,
virtual public CombinedInterface
{
virtual void setId(int id) { }
};
void example()
{
CombinedInterface * combinedInterface = new CompleteConcrete();
}
With virtual inheritance, the only change that's needed (besides the elephant in the room) is to have CompleteConcrete multiply-inherit from CombinedInterface, instead of SecondInterface. You can think of it this way: with CompleteConcreate in the picture, it now supports CombinedInterface, and not just the addition of SecondInterface.
Some frown on virtual inheritance. I don't. It's one of the unique features of C++, that no other high level language shared, TMK. It's a very powerful tool, and can solve certain problems that would be hard to solve in other ways. The two main disadvantages of virtual inheritance are:
Because it is so powerful, it can be easily misused, and lead to various problems.
If virtually-inherited classes have non-default constructors it quickly becomes painful, because every class that virtually inherits something is now responsible for constructing it.
But as long as virtual inheritance is used correctly, and the involved classes can take of constructing themselves, virtual inheritance is a useful tool.
P.S. I'll also mention one other alternative solution that just came to mind. If, say you have your CombinedInterface just so that it can be required for some particular function, like:
void somefunction(CombinedInterface &object);
Your function requires a combined interface.
Make a small change:
void somefunction(FirstInterface &first, SecondInterface &second);
and pass the same object as both parameters. You can pass CompleteConcrete, that implements both interfaces, without any changes to your class hierarchy. You could also have a template facade that makes it look like the function still takes one parameter:
template<typename T> void somefunction(T &&t)
{
real_somefunction(std::forward<T>(t), std::forward<T>(t));
}
void real_somefunction(FirstInterface &first, SecondInterface &second);
You can pretty much get rid of CombinedInterface, and simply pass any object that implements both interfaces to somefunction(), and your real_somefunction() will use one or the other parameter to invoke the appropriate interface.
Say you need to carry a pointer to an object that implements both interfaces?
class combined_pointer : public std::pair<FirstInterface *, SecondInterface *> {
public:
template<typename T> combined_pointer(T *t)
: std::pair<FirstInterface *, SecondInterface *>(t, t)
{}
};
Just a starting point.
I've used virtual inheritance.
This compiled successfully with a warning, but I think it is ok.
class FirstInterface
{
virtual int getId() const = 0;
};
class SecondInterface
{
virtual void setId(int id) = 0;
};
class CombinedInterface : virtual public FirstInterface, public SecondInterface
{
};
class FirstConcrete : virtual public FirstInterface
{
virtual int getId() const
{
return 1;
}
};
class CompleteConcrete : public CombinedInterface, public FirstConcrete
{
virtual void setId(int id) { }
};
// warning: C4250: inherits via dominance
CombinedInterface * combinedInterface = new CompleteConcrete();
When trying to call a method setCurrentState Im getting the error:
StateMachine<Cow>::setCurrentState(std::shared_ptr<State<Cow>>)':
cannot convert argument 1 from 'std::shared_ptr<ChaseState>' to
'std::shared_ptr<State<Cow>>'
This indicates that a std::shared_ptr<ChaseState> is not a std::shared_ptr<State<Cow>> but why is it not?
The call to the function:
std::shared_ptr<ChaseState> initialState = std::make_shared<ChaseState>();
m_stateMachine->setCurrentState(initialState);
State.h
#pragma once
template <class entity_type>
class State
{
public:
virtual void enter(entity_type*) = 0;
virtual void execute(entity_type*) = 0;
virtual void exit(entity_type*) = 0;
};
ChaseState.h
class Cow;
class ChaseState : State<Cow>
{
public:
ChaseState();
// Inherited via State
virtual void enter(Cow*) override;
virtual void execute(Cow*) override;
virtual void exit(Cow*) override;
};
In my StateMachine I have private variable:
std::shared_ptr<State<entity_type>> m_currentState;
and the setCurrentState function:
void setCurrentState(std::shared_ptr<State<entity_type>> s) { m_currentState = s; }
As I understand the derived class ChaseState is a State (behause it inherits from state).
You need to declare your inheritance public. Class inheritance is private by default, meaning that you cannot cast from Derived to Base because the inheritance is not recognized outside of the class itself (same as how private members cannot be accessed outside the class).
To fix, make your inheritance public:
class ChaseState : public State<Cow>
// ^^^^^^
I get the following compilation error here. Why can't the derived class access another derived class method. Although the method is public. I am confused here. Please help.
/export/home/joshis1/Dropbox/Design_Patterns_UML/ObserverPattern/ObserverPatternProgram-build-desktop-Qt_4_8_4_in_PATH__System__Release/../ObserverPatternProgram/UpdateReceiver.h:43:
error: no matching function for call to
‘IPublisher::registerObserver(UpdateReceiver* const)’
I have a publisher class - Interface -
class ISubscriber;
/** Interface **/
class IPublisher
{
public:
virtual void registerObserver(ISubscriber *observer) = 0;
virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void notifyObserver() = 0;
virtual void setBaudRate(int newBaudRate) = 0;
virtual void setAspectRatio(int newAspectRatio) = 0;
virtual void setVolumeLevel(int newVolume) = 0;
};
//////////////////////////////////////
class ISubscriber;
class UpdateManager: public IPublisher
{
private:
QList<ISubscriber *> subscribers;
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
public:
UpdateManager()
{
qDebug()<<"Update Manager --- Server/Subject Initialized";
subscribers.clear();
}
virtual void registerObserver(ISubscriber *observer)
{
subscribers.append(observer);
}
virtual void unregisterObserver(ISubscriber *observer)
{
int index = subscribers.indexOf(observer);
subscribers.removeAt(index);
qWarning()<<"Removed the subscriber Index = "<<index;
}
virtual void setBaudRate(int newBaudRate)
{
m_baudRate = newBaudRate;
notifyObserver();
}
virtual void setAspectRatio(int newAspectRatio)
{
m_aspectRatio = newAspectRatio;
notifyObserver();
}
virtual void setVolumeLevel(int newVolume)
{
m_volumeLevel = newVolume;
notifyObserver();
}
virtual void notifyObserver()
{
#if 0
foreach( ISubscriber observer, subscribers )
{
observer.update(m_baudRate,m_aspectRatio,m_volumeLevel);
}
#endif
}
};
///////////////////
I have the observer --
/** Subscriber Interface **/
class ISubsrciber
{
public:
virtual void update(int baudRate, int AspectRatio, int VolumeLevel) = 0;
};
class UpdateManager;
class ISubsrciber;
#include "IPublisher.h"
class UpdateReceiver: public ISubsrciber
{
private:
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
int m_receiverNumber;
public:
// static int updateReceiverTracker;
/** Update Interface of the client **/
void update(int baudRate, int AspectRatio, int VolumeLevel)
{
m_baudRate = baudRate;
m_aspectRatio = AspectRatio;
m_volumeLevel = VolumeLevel;
qDebug()<<"The following client number : "<< m_receiverNumber<< " got the update ";
qDebug()<<"The baudRate is "<<baudRate;
qDebug()<<"The AspectRatio is"<<AspectRatio;
qDebug()<<"The VolumeLevel is"<<VolumeLevel;
}
/** Constructor -- and registers with the Server or Publisher or UpdateManager **/
UpdateReceiver(IPublisher *updateManager)
{
//m_receiverNumber = UpdateReceiver::updateReceiverTracker++;
updateManager->registerObserver(this);
}
};
Regarding the error message you have - you don't have a method (at least in this question) with the signature that your code is apparently looking for. You have:
virtual void registerObserver(ISubscriber *observer)
{
subscribers.append(observer);
}
Your first file describes an ISubscriber but your second file inherits from an ISubsrciber (sic).
You have a typo in your file. Change to ISubscriber and you should have better luck!
here updateManager->registerObserver(this); you are sending it object of UpdateReceiver while it requires ISubscriber.
class
class UpdateReceiver: public ISubsrciber // wrong
class UpdateReceiver: public UpdateManager // right
should inherit UpdateManager not ISubsrciber?
Well I do see a few problems along your solution. Firstly you do have different forward declarations for the type ISubscriber as I stated in my earlier comment. Which results in your program not compiling.
These two wont match for sure.
virtual void registerObserver(ISubscriber *observer) {...}
class UpdateReceiver: public ISubsrciber {...}
^^^^
Secondly your notifyObserver implementation does need some rethinking as well. But since you kind of commented that code out, I'll leave this one up to you. Just remember that you're holding pointers to ISubscriber in your subscriber list when you're trying to iterate/loop over it.
Also the definition of unregisterObserver does not match your declaration.
virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void unregisterObserver(ISubscriber *observer) {...}
BUT
I would consider some major refactorings for your code. In my opinion you should not mix up the Interface of the Observerpattern with your application logic.
I think your solution should look similar to this. It's not complete and does not use your QT classes tho but you should get the idea. See the demo for a runnable solution.
class ISubscriber {
public:
virtual void update() = 0;
};
class Publisher {
std::vector<ISubscriber*> m_observerList;
public:
virtual void registerSubscriber(ISubscriber& observer);
virtual void unregisterSubscriber(ISubscriber& observer);
virtual void notifySubscribers();
};
class UpdateManager : public Publisher {
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
public:
virtual void setBaudRate(int newBaudRate);
virtual void setAspectRatio(int newAspectRatio);
virtual void setVolumeLevel(int newVolume);
int getBaudRate() const;
int getAspectRatio() const;
int getVolumeLevel() const;
};
class UpdateReceiver : public ISubscriber {
UpdateManager& m_manager;
public:
UpdateReceiver(UpdateManager& manager) : m_manager(manager) {
m_manager.registerSubscriber(*this);
}
virtual void update() {
// Process the new values
m_manager.getBaudRate();
m_manager.getAspectRatio();
m_manager.getVolumeLevel();
}
};
DEMO
Please refer the following example.
using namespace std;
//Base interface
class IBase
{
public:
virtual void BaseMethod1() = 0;
virtual void BaseMethod2() = 0;
};
class IEntity1 : public IBase
{
public:
virtual void Entity1Method1() = 0;
virtual void Entity1Method2() = 0;
};
class Entity1 : public IEntity1
{
public:
Entity();
//IBaseMethods
void BaseMethod1();
void BaseMethod2();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
In the above example, for all other entities deriving from IBase needs to implement BaseMethod1() and BaseMethod2().Because of which lots of code duplication is happening? Is there anyway where we can avoid redundant implementation of IBase methods in entities deriving from it?
You can use virtual inheritance in combination with a default base implementation class to encapsulate your default base behavior, and have it be only inherited by the concrete classes you want, like follows:
using namespace std;
//Base interface
class IBase
{
public:
virtual void BaseMethod1() = 0;
virtual void BaseMethod2() = 0;
};
class IEntity1 : virtual public IBase
{
public:
virtual void Entity1Method1() = 0;
virtual void Entity1Method2() = 0;
};
class BaseImpl : virtual public IBase
{
public:
virtual void BaseMethod1()
{
...
}
virtual void BaseMethod2()
{
...
}
}
class Entity1 : public IEntity1, public BaseImpl
{
public:
Entity1();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
There is, however, a runtime cost associated with virtual inheritance. Multiple inheritance also comes with some structural issues, e.g. base class construction.
You can even have some fun with template classes to make your class composition more modular:
template<typename TEntity, typename TBaseImpl>
class ConcreteEntity: public TEntity, public TBaseImpl
{
public:
ConcreteEntity() {}
};
class ConreteEntity1 : public ConcreteEntity<IEntity1, BaseImpl>
{
public:
ConreteEntity1();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//ConreteEntity1 Methods
void Method1();
void Method2();
};
You could make a function that is called in BaseMethod1() implementations that are the same.
Something like this:
void BaseMethod1_common();
class Entity1 : public IEntity1
{
public:
Entity();
//IBaseMethods
void BaseMethod1() { BaseMethod1_common(); }
void BaseMethod2();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
First of all IBase deserves a virtual destructor.
Declare it pure virtual and define IBase:BaseMethod1() and
IBase::BaseMethod1().
If your intention is to hide implementation, then the only option would be to release the code as a library and then share only the header file among the other developers.
Implementing a global function, or using multiple inheritance as suggested still mean that your implementation is exposed.
However, if the intent is to reduce coupling among the various classes, there's another option :
Create a class that has the actual shared implementation, and then another class which will be an interface to it.
This interface class will then be the base class for other derived entities.
Example code is shown below :
//First Header and Cpp file
class Base_private
{
public:
BaseImpl(arguments);
~BaseImpl();
void BaseMethod1() {
//Implementation
}
void BaseMethod2() {
//Implementation
}
};
//Second Header and Cpp file
class BaseInterface
{
public:
BaseInterface(arguments);
~BaseInterface();
void BaseMethod1() {
m_pBase->BaseMethod1();
}
void BaseMethod2() {
m_pBase->BaseMethod2();
}
private:
Base_private* m_pBase;
};
class Entity : public BaseInterface
{
public:
Entity(arguments);
~Entity();
void Method1();
void Method2();
};
I want to reconstruct my small 3d-engine, it is very small so i place all files in only one project.
now, i want to reconstruct it with interfaces, so i can disperse different modules to the different projects and build them as a dll.
when i do that, i have met a lot of difficulties in the basic design of framework code.
I want to design a 'Object Hierarchy' of my small engine, it is realized in the previous work. for example:
Object
Component
SceneComponent
StaticMeshComponent/SkelMeshComponent
D3DSkelComponent
...
but they are implement directly.
now, i want to use interface(pure virtual class), i have design the basic interfaces(for test ):
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
class IObject
{
public:
virtual std::string GetName() = 0;
};
class IMesh : public IObject
{
public:
virtual void Draw() = 0;
};
class IStaticMesh : public IMesh
{
public:
virtual void BuildSomeMesh() = 0;
};
class ISkeletalMesh : public IMesh
{
public:
virtual void PlayAnim( const std::string& strAnimName ) = 0;
};
class ID3DSkeletalMesh : public ISkeletalMesh
{
public:
virtual void LoadD3D( const std::string& strD3D ) = 0;
};
it looks like ok, but when i try to implement them, i find that it may be a impossible mission.
first, i can write a template class or normal class for IObject, eg:
template < typename TBase >
class TObject : public TBase
{
public:
virtual std::string GetName()
{
return m_strTest;
}
std::string m_strTest;
};
based on this TObject, I can implement a CMesh:
class CMesh : public TObject< IMesh >
{
public:
virtual void Draw()
{
cout<<"draw mesh" <<endl;
}
};
IMesh* pMesh = new CMesh(); // ok
IObject* pObj = pMesh; // ok
so far, it works well. but how to implement the CStaticMesh/CSkeletalMesh/CD3DSkeletalMesh?
it maybe like this:
class CStaticMesh : public CMesh, public IStaticMesh
{
public:
};
but i have two IObject base class, so i must change all "public xxx" to "virtual public xxx", it looks bad.
another question is CStaticMesh must implement all virtual member function of IStaticMesh, include:
virtual void Draw() = 0;
virtual void BuildSomeMesh() = 0;
even if there is a Draw in CMesh which is a base call of CStaticMesh.
ok, maybe i need a TMesh:
template < typename TBase >
class TMesh : public TObject< TBase >
{
public:
virtual void Draw()
{
cout<<"draw mesh" <<endl;
}
};
and implement CStaticMesh like this:
class CStaticMesh : public TMesh<IStaticMesh>
{
public:
virtual void BuildSomeMesh()
{
cout<<"Build Some Mesh!"<<endl;
}
};
it looks like ok, but how to implment CD3DSkeletalMesh? make a TSkeletalMesh? ok, it is crazy!!!
i think, this is abime.
which is the mistake in this design? how to change the design idea to avoid this dilemma? do you know a idea which can keep the inheritance hierarchy of those interfaces and implement easily?
if i use many virtual inheritance, is there any performance isuue?
You can solve this, as you mentioned, with virtual inheritance. This will create only one instance of a multiply inherited interface class in the hierarchy.
First the interfaces:
class IObject
{
public:
virtual std::string GetName() = 0;
};
class IMesh : virtual public IObject
{
public:
virtual void Draw() = 0;
};
class IStaticMesh : virtual public IMesh
{
public:
virtual void BuildSomeMesh() = 0;
};
class ISkeletalMesh : virtual public IMesh
{
public:
virtual void PlayAnim( const std::string& strAnimName ) = 0;
};
class ID3DSkeletalMesh : virtual public ISkeletalMesh
{
public:
virtual void LoadD3D( const std::string& strD3D ) = 0;
};
Then the implementations:
class CObject : virtual public IObject
{
public:
std::string GetName()
{
return m_strTest;
}
std::string m_strTest;
};
class CMesh : public CObject, virtual public IMesh
{
public:
void Draw()
{
cout<<"draw mesh" <<endl;
}
};
class CStaticMesh : public CMesh, virtual public IStaticMesh
{
public:
void BuildSomeMesh()
{
cout<<"Build Some Mesh!"<<endl;
}
};
...
For the performance implications of this, look at this question.