What I would like to do is place a manager into a map, and then call functions correlating to each manager. Because I have different types of managers I created a base class like so:
class iGyroManager {
public:
iGyroManager() {}
virtual ~iGyroManager() = default;
virtual bool preInit() = 0;
virtual bool init() = 0;
virtual bool postInit() = 0;
virtual void update() = 0;
virtual void cleanup() = 0;
}
Pretty straight forward and obviously works like a charm.
Then I do the following to create a derived class:
class GyroAudioManager : public iGyroManager {
public:
GyroAudioManager();
~GyroAudioManager() override;
bool preInit() override;
bool init() override;
bool postInit override;
void update() override;
bool cleanup() override;
}
Again, simple and straight forward. The cpp is very basic and just declares the bare functions.
I then create one final derived class:
class GyroAppStateManager : iGyroManager {
private:
std::map<int, iGyroManager&> m_managerMap;
public:
GyroAppStateManager();
~GyroAppStateManager() override;
bool preInit() override;
bool init() override;
bool postInit() override;
int start();
void update() override;
bool registerManager(iGyroManager& manager);
bool cleanup() override;
}
That seems to work, but it's in the registerManager function where it falls apart:
bool GyroAppStateManager::registerManager(iGyroManager& manager) {
// Try to insert a derived class into a base class map using what
// should be working.
m_managerMap.insert(1, manager);
return true;
}
And in the calling function:
int start() {
GyroAudioManager m_audioManager = GyroAudioManager();
mp_appStateManager->registerManager(m_audioManager);
/* use mp_appStateManager here, while m_audioManager is alive */
}
Except this does not seem to work at all and spits out the following:
error: no matching function for call to std::map<int, iGyroManager&>::insert(int, iGyroManager&)
So my question is what am I doing wrong? As I mentioned above, I'd like to add multiple different manager classes that derive a single base class to this map and then be able to run certain functions from it.
Is there actually a way of doing it?
You can't have a standard container of references. I'm still looking for the exact wording of the restriction, but in the meantime you might want to try std::reference_wrapper instead, or a container of (smart) pointers, which also allows polymorphism.
Actually, value_type is std::pair<key_type, mapped_type> which is an object type even when mapped_type is a reference. So that's ok.
The error is caused because the parameter to std::map<Key,Value>::insert is a pair<Key,Value>, not two separate arguments. Try
m_managerMap.insert({1, manager});
But then you need to arrange to reference an object that isn't destroyed immediately afterward, when start() returns.
Related
I have a pure virtual class Interface:
class Interface {
public:
virtual ~Interface() noexcept;
virtual void open()=0;
virtual void close()=0;
protected:
explicit Interface(const string params);
string params_;
}
I then have an abstract class where I implement my business logic:
template<typename T>
class AbstractInterface : public Interface {
public:
void open() override;
void close() override;
void read_is_complete(const vector<byte_array>);
protected:
explicit AbstractInterface(const string params);
virtual ~AbstractInterface() noexcept;
}
Then there is the implementation for the interface that uses CRTP for polymorphism:
class SPInterface : public AbstractInterface<SPInterface> {
public:
explicit SPInterface(const string params);
virtual ~SPInterface() noexcept;
void open();
void close();
void read_is_complete(const vector<byte_array> data);
}
I have a unit test where I create an instance of SPInterface:
unique_ptr<Interface> intf;
intf.reset(new SPInterface("aaa"));
Letting this get out of scope calls the destructor AbstractInterface which in turn calls the close method on AbstractInterface and then it segfaults on this:
template<typename T>
void AbstractInterface<T>::close() {
static_cast<T *>(this)->close();
params_ = "";
}
Which is confusing as I already created an instance of the class. lldb seems to confirm:
AbstractInterface<SPInterface>::close(this=<unavailable>)
Letting this get out of scope calls the destructor AbstractInterface which in turn calls the close method on AbstractInterface and then it segfaults on this:
template<typename T>
void AbstractInterface<T>::close() {
static_cast<T *>(this)->close();
params_ = "";
}
It seems that you are trying to invoke a method of a derived class from within the destructor of a base class.
This is not safe at all and a segfault is the way the executable has to tell you that it doesn't approve that. :-)
Even though CRTP allows you to invoke a member function that belongs to the derived class on a (let me say) living object, it doesn't change the way an object is destructed.
Do not forget that bases and members are destroyed in the reverse order of the completion of their constructor.
Say I have such classes:
class Scene {
public:
Scene(void);
~Scene(void);
virtual void update(void) = 0;
virtual void construct(void) = 0;
virtual void destroy(void) = 0;
};
class KillTheHedgehogScene : public Scene {
public:
virtual void update(void) override;
virtual void construct(void) override;
virtual void destroy(void) override;
EntitySceneGraph sceneGraph;
};
and I have a SceneManager class that goes something like this:
class SceneManager {
public:
SceneManager(void);
void loadNewScene(Scene* scene);
Scene* getCurrentScene(void);
void update(void);
private:
Scene* _currentScene;
};
The way my code functions now, I would load a new scene by doing the following:
_sceneManager->loadNewScene(new KillTheHedgehogScene());
My issue with this is that whatever scope this is in has made the allocation, and now _sceneManager has to be in charge of it's deallocation. I want the SceneManager to handle both allocation and deallocation. I want to be able to call my loadNewScene() function in this way:
_sceneManager->loadNewScene<KillTheHedgehogScene>();
This way the scene manager can handle both the allocation and deallocation of the object, and gives it all control. My question however is how can I have templates restrict an input type based on inheritance. For example, I wouldn't want to be able to call:
_sceneManager->loadNewScene<SomeRandomOtherClass>();
SomeRandomOtherClass is not a child class of Scene. Is there a way to restrict the type?
To have a better error message when providing invalid template parameter, you may add static_assert, something like:
template <typename T>
void loadNewScene()
{
static_assert(std::is_base_of<Scene, T>::value, "Type should inherit from class Scene");
// Your implementation
}
Using the following two classes...
//pure virtual...
class Monkey
{
public:
virtual ~Monkey(){}
virtual void clearMonkeys() = 0;
virtual std::shared_ptr<std::vector<sf::Text>> getMonkeyListPtr() = 0;
virtual void addMonkey(String message,Vector2f position,float depthValue) = 0;
};
class NullMonkey : public Monkey
{
public:
NullMonkey () {/*Do Nothing*/}
virtual ~NullMonkey () {/*Do Nothing*/}
virtual void clearMonkeys(){/*Do Nothing*/};
virtual std::shared_ptr<std::vector<sf::Text>> getMonkeyListPtr()
{
//Do Nothing but...
//Return NULL shared pointer
std::shared_ptr<std::vector<sf::Text>> nullSharedPointer;
return nullSharedPointer;
//Of course I am ASSUMING I will check for NULL pointer...
}
virtual void addMonkey(String message,Vector2f position,float depthValue){/*Do Nothing*/};
};
...I have issues when casting.
Specifically I am using these classes as static members and have a situation where if one class is not available I use the Null class to fall back on to prevent app crash. It also adds the ability to hot-swap child classes for debug purposes.
Unfortunately the following...
class ServLoc
{
public:
ServLoc();
static void initialize()
{
theMonkey = &theNullMonkey; //Error here
}
//...
static Monkey* theMonkey;
static NullMonkey theNullMonkey;
};
...throws 'cannot convert NullMonkey* to Monkey* in assignment'.
I should also add add I have defined the static members in the .cpp file
NullMonkey ServLoc::theNullMonkey;
Monkey* ServLoc::theMonkey;
The funny thing is I have used similar classes in similiar situations before and did not get this error. I am at a loss. It is probably something simple but still...
In fact I implement a log class using this method. It means I can hot-swap various forms of logging (including the null logger to disable logging) and have access to the logger wherever by just using the ServLoc static members...
class Logger
{
public:
virtual ~Logger() {}
virtual void log(const logType type,const char *message) = 0;
//...
};
class NullLogger : public Logger
{
public:
virtual ~NullLogger() {/*Do Nothing*/};
NullLogger() {/*Do Nothing*/};
virtual void log(const logType type,const char *message) {/*Do Nothing*/};
//...
};
This when used in same way in ServLoc as shown above works fine!?
Any ideas?
Regards
Edit - Fixed spelling mistakes
I suspect (could you clarify?), that you are calling the static function initialize() from another statically initialized class? Since this would all be done at program startup (and C++ does not guarantee any static initialization order between files), initialize may be called before ServLoc::theNullMonkey; has been constructed?!
I'm trying to implement the observer pattern in C++. What I attempting to do is to declare an observer interface with a single pure virtual method: notify(), and then let the the observers implement/derive that interface. Additionally, I want to keep a vector of pointers to all the observer classes in the observed class, so that I can call notify() on each of them. Sadly I'm having some trouble with the vector of pointers.
This is the observer interface:
class LocationEstimateObserver {
public:
virtual void notify() = 0;
};
I have two different classes implementing this interface. Hence, both implement the notify() method.
Here my observed class:
class Simulator {
public:
Simulator();
virtual ~Simulator();
void registerListener(LocationEstimateObserver& observer){observers_.push_back(&observer); };
void notifyObservers();
private:
std::vector<LocationEstimateObserver*> observers_;
};
And the observer class (implements the observer interface):
void InMapsEngine::startSimulation() {
Simulator sim();
sim.registerListener(*this);
}
And the Simulator.cpp file:
void Simulator::notifyObservers() {
for (unsigned int i = 0; i < observers_.size(); i++) {
observers_.at(i)->notify();
}
}
Now when I run the above code I get a segmentation fault. Could anyone of you point out what what I am doing wrong? I'm very new to C++.
EDIT: I just made a bizarre discovery: when I call observers_.size() it returns a very odd negative number, so the for loop fails. There lies the problem.
Why instead of adding instances of subclasses of LocationEstimateObserver, don't you have a vector of functions that will be notified when something will occur?:
Something like:
class Simulator {
public:
Simulator();
virtual ~Simulator();
void registerListener(const function<void()>& observer ) {observers_.push_back(observer); };
void notifyObservers();
private:
std::vector<function<void()>> observers_;
};
void observer1()
{
}
int main()
{
Simulator sim;
sim.registerListener(observer1);
}
And the Simulator.cpp file:
void Simulator::notifyObservers() {
for (auto& observer : observers_)
observer();
}
You keep a vector of pointers to objects that could have been deleted right after being registered. Make sure they are still there when you call Simulator::notifyObservers().
In the following exceedingly abbreviated classes I would like to define in the base a method (ProcessLines) that would iterate over a set of database records, passing each record as a parameter to a function that is only defined in the child class. Obviously the Base is a virtual class that will never be instantiated on its own.
Class Base {
public:
typedef ProcLineFunc( Long *Line );
void ProcessLines( ProcLineFunc pf);
}
Class Child{
void DoWork( Long *Line) { //do something}
}
I'm not sure how to implement this. If I redeclare ProcessLines in the child and just call the parent method, I get the same error message as if I call ProcessLines in the code that creates the child.
Child c(//something);
c.ProcessLines(c.DoWork);
Gives me a compiler message:
[BCC32 Error] main.cpp(67): E2034 Cannot convert 'bool (* (_closure )(long *))(long )' >to 'int ()(long *)'
Full parser context
main.cpp(56): class Add2Chan
main.cpp(78): decision to instantiate: bool Add2Chan::ProcessByLines()
--- Resetting parser context for instantiation...
main.cpp(67): parsing: bool Add2Chan::ProcessByLines()
I'm fairly new to c++ and the E2034 error message scares the daylights out of me.
Please help. I used a typedef so that I can, in my child classes call ProcessLines multiple times, passing in different functions as I go.
Normally you would do this sort of thing with a protected, pure virtual function:
class Base {
public:
ProcessLines() {
//Logic to process lines here, obviously psuedo-code
while(moreLines) {
ProcessLine(line);
}
}
protected:
virtual void ProcessLine(const Line& line) = 0;
}
class Child : public Base {
protected:
void ProcessLine(const Line& line) { //Logic to process the line for this type }
};
class DifferentChild : public Base {
protected:
void ProcessLine(const Line& line) { //Logic to process the line for DifferentChild }
};
I think this is the kind of thing you're looking for. It appears to me like you're trying to implement polymorphism in an odd way, but this is the normal way to do it in C++.
Instead of using pointers to functions, use pointers to objects. Accept the limitation that your function is going to be called DoWork and nothing else, and there can only be one such function in each class. This is not a bad limitation. Declare the (pure virtual) function in a class (which is called an interface), and derive classes from it (they are said to implement an interface).
struct DoingWork
{
virtual void DoWork(long *Line) = 0; // does some work on a list
};
struct DoingGreatWork: DoingWork
{
virtual void DoWork(long *Line) {printf("Great work\n");}
};
struct DoingSlightWork: DoingWork
{
virtual void DoWork(long *Line) {printf("Slight work\n");}
};
Using this example:
class Base {
public:
void ProcessLines(DoingWork& object) {
//Logic to process lines here
while(moreLines) {
object.DoWork(line);
}
}
};
class Whatever // no need to derive from Base
{
void DoStuff()
{
Base object;
object.ProcessLines(DoingGreatWork());
object.ProcessLines(DoingSlightWork());
}
}
If the working objects have to have access to the calling object, initialize them like this:
class Whatever // no need to derive from Base
{
struct DoingElaborateWork: DoingWork
{
Whatever& caller;
DoingElaborateWork(Whatever& caller): caller(caller) {}
virtual void DoWork(long *Line)
{
printf("Doing work requested by %s\n", caller.name());
}
};
void DoStuff()
{
Base object;
object.ProcessLines(DoingElaborateWork(*this));
}
const char* name() {return "Whatever";}
}
P.S. They say that "in C++03 functions are second-class citizens" because you cannot do with functions what you can do with objects (like this solution i provide). I heard that in C++11 functions are much improved, but i am not sure about the details.
Since you are doing this in C++Builder, you can utilize its __closure extension to do exactly what you asked for (some portions of the VCL do exactly this for their own callbacks):
class Base
{
public:
virtual ~Base() {}
typedef void (__closure *ProcLineFunc)( Long *Line );
void ProcessLines( ProcLineFunc pf);
};
class Child : public Base
{
public:
void DoWork( Long *Line) { //do something}
};
Child c(...);
c.ProcessLines(c.DoWork);