I'm sorry if I don't know the right word for what I'm trying to accomplish.
Basically I have an event handler object which only has a single member. The member is a Stage object.
When the event handler receives an event, I want it to simply use the stage object to call the relevant method. For example:
Event event; //this event is not part of my code, but rather the library I'm using.
Stage s; // my custom class object
EventHandler event_handler; //also my custom class object
event_handler.stage = &s;
if(event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
So what I'm trying to accomplish is that, there will be seperate scopes that my program goes into over time, and I want each scope to have access to the event_handler such that they can do something like:
void some_other_scope(EventHandler* eh) {
Stage* some_new_stage = new Stage(...);
eh->stage = some_new_stage;
}
This way, the original event code stays the same, and the event handler will be calling handle_shutdown on a different object than it was originally going to.
So what I want to do is to overload the handle_shutdown method so that there can be different implementations of it. I know how basic overloading works, it can be done by specifying different parameters, but is there any way to have different definitions of the same class method based on the file that the object was created in?
I was hoping to have several files, each with their own some_other_scope() function, and each file can redefine the handle_shutdown method to do different things based on what that file needs.
I'm sure there's a way to do what I want, I just don't know the right words to use.
It seems you want to use polymorphism:
class IStage
{
public:
virtual ~IStage() = default;
virtual void handle_shutdown() = 0;
// ...
};
class Stage1 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
class Stage2 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
And then
struct EventHandler
{
std::unique_ptr<IStage> stage;
// ...
};
EventHandler event_handler;
event_handler.stage = std::make_unique<Stage1>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
// Later
event_handler.stage = std::make_unique<Stage2>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
Related
I am a beginner with google testing framework and have looked up for the solution to this question on SO, but could not find any solutions with respect to C++. Anyway here is what i am trying to do. I have a state machine(service) which is called inside a client code.
//IStateMachine.h
class IStateMachine
{
public:
bool Run(const std::string& action) = 0;
bool IsTxnValid(const std::string& action)= 0;
}
//StateMachine.h
class StateMachine : public IStateMachine
{
bool Run(const std::string& action) override;
bool IsTxnValid(const std::string& action) override;
}
//StateMachine.cpp
bool StateMachine::IsTxnValid(const std::string& action)
{
//Checks whether the given action is valid for the given state.
}
bool StateMachine::Run(const std::string& action)
{
if(IsTxnValid(action)) // #E
{
//Do processing
return true;
}
return false;
}
//Client.h contains a class Client which has function called RunService.
Client
{
public:
void RunService();
std::unique_ptr<IStateMachine> service_; // Initialised to a non null value in either ctr or
// factory.
}
//Client.cpp
bool Client::RunService(std::string&action)
{
if(!service_->Run(action)) //Run in turn calls IsTxnValid().
{
return false;
}
return true;
}
Now i am writing a test case to test the functioning of RunService. I am expecting that if Client::IsTxnValid(param) returns false, then so should RunService.
I have successfully set up the testing recipe and could get the basic tests running. Here is the relevant test i have written. On running this test the i get the error, that IsTransitionValid is never called.
TEST_F(ClientTest, RunService)
{
EXPECT_CALL(*p_service, Run("some_action")); // #A
// EXPECT_CALL(*p_service, Run(testing::_)).WillOnce(::testing::Return(true)); //#B
EXPECT_CALL(*p_service,IsTransitionValid(testing::_)).WillOnce(::testing::Return(false)); //#C : This never gets called.
EXPECT_EQ(false, x_client->RunService());
}
How do i correctly call IsTransitionValid ?
You don't need to set this expectation. I'd go even further: you should not even depend on the implementation of Run in IStateMachine: you should only care about what input it is provided with (parameters, checked with matchers) and what output it can return (so basically only the contract between these two classes) and that's the beauty of it!
It is an implementation detail of StateMachine class (the real implementation) what is done when Run is called. The only thing you need to check in your test is to act upon the result of Run. Using triple A rule (arrange, act, assert): you arrange the test case conditions (using EXPECT_CALLs), then you act (calling RunService) and then you assert (checking the result of RunService).
The technical details:
When you create a mock by inheriting from class Foo:
class Foo {
public:
virtual ~Foo() = default;
virtual void bar() = 0;
}
By defining:
class FooMock : public Foo {
MOCK_METHOD0( bar, void());
}
gmock will add bar (the method to override) and gmock_bar (internal detail of gmock) methods to FooMock class. bar has empty implementation in this case. FooImpl and FooMock share the interface, but have different implementations - hence no call to IsTxnValid is made in Run: the mock class just doesn't know (nor care) how Run is implemented in StateMachine. Remember: in your testcase you interact with StateMachineMock and you only care about the interaction with its public interface, the contract between these two classes and how they cooperate together.
That being said, you of course need to utest the StateMachine class. It may depend on yet another interfaces in its implementations: that will be tested with different set of mocks. But Client should not know about this.
In below code snippet I do require to instantiate the object through factory method in order to call the selected adapter (i.e. adapterTwovalue)but while calling through factory method i am not able to get the desire results. When we assign static declared object's address (i.e adapter = &at) it works but with factory i usually get the blank output.
I tried as well with (adapter = new adapterTwo()) to instantiate the object but output string is giving blank results. As per my requirement i need to populate the all the getters in connect function which is pure virtual function to frame the response.Anybody can suggest how to achieve this using factory method.
#include <iostream>
using namespace std;
class IAdapter
{
public:
enum FactoryList { AdapterOnevalue = 0, AdapterTwovalue };
virtual void connect() = 0;
static IAdapter* CreateList(FactoryList);
virtual ~IAdapter() {}
};
class LibraryOne
{
string property;
public:
void SetConnection(string property)
{
this->property = property;
}
string getConnection()const
{
return property;
}
};
//LibraryTwo
class LibraryTwo
{
string broker;
public:
void SetBroker(string broker1)
{
this->broker = broker1;
}
string getBroker() const
{
return broker;
}
};
//adapterOne
class AdapterOne : public IAdapter
{
LibraryOne one;
string constring;
public:
void SetClientconnection(string constring)
{
one.SetConnection(constring);
}
string GetClientconnection()
{
return one.getConnection();
}
void connect()
{
constring = GetClientconnection();
}
};
//Adapter to use library two
class AdapterTwo : public IAdapter
{
LibraryTwo two;
string brokerstring;
public:
void SetClientbroker(string constring)
{
two.SetBroker(constring);
}
string GetClientbroker()
{
return two.getBroker();
}
void connect()
{
string constring = GetClientbroker();
cout << "final value=" << constring;
}
};
IAdapter* IAdapter::CreateList(FactoryList SelectList)
{
IAdapter *ListObject;
switch (SelectList)
{
case AdapterOnevalue:
ListObject = new AdapterOne();
break;
case AdapterTwovalue:
ListObject = new AdapterTwo();
break;
default:
ListObject = NULL;
}
return ListObject;
}
int main()
{
IAdapter *adapter = 0;
//LibraryTwo obj;
AdapterTwo at;
at.SetClientbroker("amqp");
//cout << at.GetClientbroker();
//adapter = &at; it works
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);//it doesn't work
//Just do the operation now
adapter->connect();
return 0;
}
You can see the complete solution in below share link.
http://coliru.stacked-crooked.com/a/d8b9d32a1fa989c9
Here is the explanation.
(1) setClientBroker() or all other adapters related setter functionality needs to be implement as a virtual function in Interface with default parameter value " " (blank string).
(2) you need to always use override keyword (c++11) feature in derive class for setters so that compiler will cross check during compilation whether proper virtual method is being overridden or not.
(3) instead of using local raw pointer , always use smart pointer . below is the
implementation link for the same.
http://coliru.stacked-crooked.com/a/2feea991ee90d4a2
With your code I expect the output: final value=.
It will not print final value=amqp cause you need to call SetClientbroker("amqp") on the right adapter object (adapter in your example).
Anyway, I would think about putting a virtual method SetString in the base class, so you could simply do:
int main()
{
IAdapter *adapter = 0;
//LibraryTwo obj;
//AdapterTwo at;
//at.SetClientbroker("amqp");
//cout << at.GetClientbroker();
//adapter = &at; it works
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);//it doesn't work
//Just do the operation now
adapter->SetString("amqp");//<---------
adapter->connect();
return 0;
}
EDIT after the comment:
You need to cast the object, at this point (as suggested by #Aconcagua).
But IMHO it's not elegant at all. I think you are going to loose the benefits gained with the factory method.
IAdapter* adapter = nullptr;
AdapterTwo at;
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);
You have created two independent objects here (as calling new within createList): at and the one adapter points to.
AdapterTwo at;
at.SetClientbroker("amqp");
Now sure you get the expected output if you let adapter point to at, but how could the other object be aware of the string you set in the first one?
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);
adapter->SetClientbroker("amqp"); // (*) !!!
You need to set the broker at the other object, too. As being different objects, you even can set the brokers independently:
AdapterTwo at;
at.SetClientbroker("amqp");
IAdapter* adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);
adapter->SetClientbroker("aconcagua"); // (*) !!!
Output now would be (if you called connect on both objects):
final value=amqp
final value=aconcagua
Only: The marked lines ((*)) won't compile as your base class does not provide the appropriate setter!
There are now different solutions for this problem. You could, for instance, just cast the object:
// if you are REALLY 100% sure the object is of appropriate type:
static_cast<AdapterTwo*>(adapter)->setClientBroker("...");
// if NOT:
AdapterTwo* a2 = dynamic_cast<AdapterTwo*>(adapter);
if(a2)
a2->setClientBroker("...");
else
// appropriate error handling
You could find a more generic name for the set/get Broker/ClientConnection functions, have them already pure virtual within IAdapter and override them in the two implementing adapter classes, so you could then just call adapter->setXYZ("ampq");. [Edit: according to your comment to the question, not an option in the given case]
My personal favourite is providing an additional parameter to your createList function such that the setter would already be called within the factory - possibly with appropriate default: empty string, if you opt for a std::string parameter, or nullptr in case of char const*. You'd only call the setter if the parameter is not matching the default, of course... Alternatively, you could have two overloads.
I have an observer (or "listener") pattern implemented in my code as such:
struct EntityListener
{
public:
virtual void entityModified(Entity& e) = 0;
};
class Entity
{
public:
Entity();
void setListener(EntityListener* listener);
private:
EntityListener* m_listener;
};
Now, this works in C++; the Entity class calls the entityModified() method whenever it needs. Now, I'd like to transfer some of the functionality to Lua, and among those function points is this listener callback. The entities are now created from the Lua scripts. The question is, how do I achieve the listener functionality in Lua?
For example, the Lua script currently does something like this:
function initializeEntity()
-- The entity object is actually created in C++ by the helper
Entity = Helper.createEntity()
-- Here I'd like to hook a Lua function as the Entity's listener
end
One possible solution is to have a LuaListener class in your C++ code that contains a "pointer" to the Lua function, and a Lua-specific setListener function that is called from the Lua script that takes a Lua function as argument, and creates a LuaListener instance and passes that to the actual C++ setListener.
So the Lua code would look something like
function onModified(entity)
-- ...
end
function initializeEntity()
entity = Helper.createEntity()
entity.setListener(onModified)
end
And the C++ code would look something like (pseudoish-code only):
class LuaListener : public EntityListener
{
private:
lua_State* state;
std::string funcName;
public:
void entityModified(Entity& e)
{
// Call function `funcName` in `state`, passing `e` as argument
}
};
class LuaEntity : public Entity
{
public:
void setListenerLua(state, funcName, ...)
{
Entity::setListener(new LuaListener(state, funcName, ...));
}
};
I need to refactor class, which handles requests. I don't need chain of responsibility, because in compile time I have specified which request is connected to which handler.
My idea is to create one singleton class which is responsible for all logic.
For example it will have pointer to database object and it will handle requests.
There will be interface for HandlerMessage and many class derived from them.
Suppose we have:
class Singleton {
Database db;
int handleMessage(const Request& in, Response& out);
};
int Singleton::handleMessage(const Request& in, Response& out) {
int result = 0;
HandlerMessage* handler;
if(in.type == RequestType::A)
handler = new HandlerA();
else if(in.type == RequestType::B)
handler = new HandlerB();
else
return -1;
result = handler->handle(in, out);
delete handler;
return result;
}
However HandlerMessage needs to use Database and I wonder how to get use them.
I can pass pointer to database as an argument of handle function in HandlerMessage class.
However it seems to me strange, because all time I will pass the same argument. Moreover not all handlers needs to use database.
My question is:
class MessageHandler {
static Database* db;
}
this a good solutions, where I initialized db from MessageHandler class with db from SingeltonClass in Singleton constructor?
Or it is better to use more sophisticated solutions?
Thank You for any reply!
You can pass the reference to the database in the constructor of the handler like this:
handler = new HandlerA(db); //HandlerA needs to deal with database
handler = new HanlderB(); //HandlerB doesn't need to deal with database
HandlerA can look like this:
class HandlerA : public MessageHandler
{
HandlerA(Database& db) { /* ... */ }
int handle(const Request& in, Response& out) { /* ... */ }
};
I have a state machine with one state which dispatches some message (e.g. text) to an external receiver. Before transiting to this state (let's call it Dispatching) previous state needs somewhere to store that message so Dispatching can fetch it later. As message is created in one context and consumed in another, it will be created on the heap and State Manager object (which manages states, transitions and event loop) keeps a reference/pointer to it. State objects are created and destroyed as state machine transits through states. Each state inherits abstract base class State:
enum StateID
{
STATE_A,
STATE_B,
...
};
class State
{
public:
State(StateID stateID, StateManager& sm) :
stateID_(stateID), sm(sm_){}
virtual ~State(){};
virtual StateID HandleEvent(const Event& e) = 0;
StateID id() const {return stateID_;}
protected:
StateID stateID_;
StateManager& sm_;
};
In order to make passing data to the next state generic, I came up with the idea of StateData - a piece of information passed from one state to the next one. It is stored in dynamic memory, State Manager keeps a reference to it so each state can access it. As it is possible that different types of data will be passed to different states, StateData can be made abstract base class, specialized for each particular state:
struct StateData
{
virtual ~StateData() = 0;
};
struct StateAData : public StateData
{
int n_;
StateAData(int n) : n_(n){}
};
struct StateBData : public StateData
{
std::string str_;
StateBData(const std::string& str) : str_(str){}
};
...
class StateManager
{
boost::scoped_ptr<State> pCurrState_;
boost::scoped_ptr<StateData> pStateData_;
...
public:
void runEventLoop()
{
while(true)
{
...
//get event from a queue
...
StateID nextStateID = pCurrState_->HandleEvent(e);
if(nextStateID == pCurrState_->id())
continue;
pCurrState_.reset(0);
switch(nextStateID)
{
case STATE_A:
pCurrState_.reset(new StateA(*this));
break;
case STATE_B:
pCurrState_.reset(new StateB(*this));
break;
case STATE_C:
pCurrState_.reset(new StateC(*this));
break;
...
}
}
}
...
};
class StateA
{
public:
StateA(StateManager& sm) : State(STATE_A, sm){}
StateID HandleEvent(const Event& e)
{
switch(e.ID)
{
case EVENT_1:
{
StateAData* pData = reinterpret_cast<StateAData*>(stateMachine_.pStateData_.get());
// do something with data, e.g. use it for transition logic
if(pData->n_ % 2)
{
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_B;
}
else
{
...
}
break;
}
...
}
}
...
}
There is a pitfall in following lines:
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_B;
If transition logic changes so from here we need to go to STATE_C, developer can forget to change the type of StateBData to StateCData:
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_C;
...which would lead to undesired behaviour when StateC tries to cast down StateData to StateCData.
How to avoid this? How to enforce matching the type of created object and returned enum value?
Yeah, this code stinks and this is the consequence of using two piece information and using enum to distinguish state types instead of types themselves. HandleEvent could return StateXData and depending on this returned type (as it carries the information about the next state) State Manager would determine (by using RTTI) the next state to transit to (X) but I don't like this solution.
Another idea is to create an instance of the next state and pass its data into its constructor but this approach would pollute state machine design as one state would be created before previous state is destroyed.
Make the enum part of the base class or provide a pure virtual function in the base class to return this enum. This way, the state itself will advertise its type.