I have multiple handlers derived from base Handler class which can do single data updates individually.
For eg.
class Handler {
public:
Data_t dbdata_;
public:
virtual void updateFlags() = 0;
}
class AHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; }
}
class BHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagB = 1; }
}
class CHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagC = 1; }
}
Individual handlers are called based on input flags in request. If request contains multiple flags, then in this case I want to try to avoid creating additional 6 handlers individually like following.
class ACHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; dbdata_.flagC = 1; }
}
class ABCHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; dbdata_.flagB = 1; dbdata_.flagC = 1 }
}
Main function code will be something similar to this.
void process(Request_t *request)
{
Handler *handler;
if (request->flagA)
handler = new AHandler();
else if (request->flagB)
handler = new BHandler();
....
...
handler->updateFlags();
}
Is there a better way to approach this problem, by re-writing how the handlers are connected to each other ?
Thanks in advance.
If this is all your classes do, then I dont think u need any other class then Handler. Just simply let the Handler handle all the flags. It will be easy and simple like that. I think you might be overthinking this. Get a working simple version and then review it and decide if u need to and can refractor it.
I dont know what type your Request_t->flag(x) and Data_t->flag(x) is.
But cant you just do
dbdata_.flagA = request_t.flagA;
dbdata_.flagB = request_t.flagB;
etc. If you can maybe make them an array instead of individual variables, for easier setting.
You may want to consider a policy-based class design. For this, we define both a variadic function template, execute(), and a class template, HandlerHolder, that inherits from Handler and overrides the updateFlags() member function:
template<typename FlagUpdater, typename... FlagUpdaters>
void execute(Data_t& data) {
execute<FlagUpdater>(data);
if constexpr (sizeof...(FlagUpdaters))
execute<FlagUpdaters...>(data);
}
template<typename... FlagUpdaters>
class HandlerHolder final: public Handler {
public:
void updateFlags() override {
if constexpr (sizeof...(FlagUpdaters))
execute<FlagUpdaters...>(dbdata_);
}
};
To this variadic class template, HandlerHolder, you can pass classes (i.e., policies) as template arguments that are callables and set the proper flags. The function call operator (i.e., operator()) of these policy classes are called in its overridden member function updateFlags().
You would then define the policy classes like:
struct AFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagA = 1;
}
};
struct BFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagB = 1;
}
};
struct CFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 1;
}
};
Note that you can also easily define policies for clearing the flags, for example:
struct CFlagClearer {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 0;
}
};
By means of type aliases you can introduce type names for the handlers you were looking for:
using ACHandler = HandlerHolder<AFlagSetter, BFlagSetter>;
using ABCHandler = HandlerHolder<AFlagSetter, BFlagSetter, CFlagSetter>;
Related
My goal is to construct a derived classes nested class from the interface. However the nested classes don't have the same constructors. The question is how can I make an interface to create two different "sub-nested" classes.
Constraints:
Cannot use Heap
Nested Classes' Methods cannot be called before it is constructed
C++ 17
ITest::INestedTest* MakeTest(ITest* test, ITest::Config config)
{
// Can't call directly because it's not on the interface i.e. test.InitializeNestedTest ...
// Only workable situation is this:
if (condition)
{
auto myTest = static_cast<Test2::Test*>(test);
int p = 2;
return myTest->InitalizeNestedTest(config, p);
// ERROR function returning abstract class not allowed
} else {
auto myTest = static_cast<Test1::Test*>(test);
return myTest->InitalizeNestedTest(config);
// ERROR function returning abstract class not allowed
}
}
This static cast didn't return what I wanted previously because I was returning a pointer to a locally defined variable, which was pointed out in the comments. How am I able to return a class from this since it's an abstract class, do i need to cast it again or make multiple functions?
Test1::Test myTest;
auto myNestedTest = myTest.InitializeNestedTest(config);
I've thought of a few options but none of them seem right, or I'm not entirely sure how to implement them
Have an overloaded Virtual function for each type on the interface and then override them on the subclass (not sure if possible and doesn't seem like the right way to do it)
Extend the Config struct Test2 namespace so that it includes parameter p, so that they all have the same prototype and put it on the interface. (is it possible to "extend" the struct" from the interface?)
Maybe use a different type of cast, or do so in a different way?
I've included the definitions of my Interface and two subclasses for reference.
class ITest
{
//other things in ITest.hpp not relevant to question
public:
struct Config
{
int a;
bool enable;
};
class INestedTest
{
public:
virtual void Enable() const = 0;
virtual void Configure(Config const& config)
{
if(config.enable)
{
Enable();
}
}
};
};
namespace Test1
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
NestedTest(Config const& config)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config)
{
return NestedTest(config);
}
};
};
namespace Test2
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
using Parameter = int;
NestedTest(ITest::Config const& config, Parameter p)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config, NestedTest::Parameter p)
{
return NestedTest(config, p);
}
};
};
Maybe you could make the object static so it's declared in RAM at compile time (and not heap or stack).
This may be impossible so alternative solutions to the problem will suffice as well
I have a list of activities that I want to keep track of
class Activity {
public:
virtual void DoSomething() = 0 ;
};
std::vector<Activity*> activities;
Let's say I have the following child classes
class GraphicsActivity : public Activity {
public:
virtual void DoSomething() { }
void HandleGraphics() { /* do some management */; }
};
class UpdateActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
class PhysicsActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
Now let's say we want to grab one of these activities from our list. A function would look like
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
T* cast = dynamic_cast<T*>(activities[i]);
if(cast != nullptr) {
return cast;
}
}
return nullptr;
}
We could use it like so:
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
GraphicsActivity* g = GetActivity<GraphicsActivity>();
Let's say we have another activity that needs to use polymorphism to use some of the base class's methods.
class 3DGraphicsActivity : public GraphicsActivity {
public:
void Handle3DGraphics() {
/* Utilize base class function */
this->HandleGraphics();
/* do some extra work */
}
};
Now we want to acquire the same activity as before and our list now looks like the following in the exact order:
activities.push_back(new GraphicsActivity3D());
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
But we want the original type of GraphicsActivity, so we go to acquire it:
GraphicsActivity* g = GetActivity<GraphicsActivity>();
We'll actually get a pointer to the first entry in the list because it shares a base class of type GraphicsActivity.
Herein lies the problem: how can I write such a list whose items must share the same base class Activity while also be able to acquire the exact type from the list without falling into the dynamic_cast trap we just explained?
The typeid operator can be used to check if a polymorphic object has a certain exact most-derived type.
#include <typeinfo>
// ...
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
auto* act = activities[i];
if (act != nullptr && typeid(*act) == typeid(T)) {
return dynamic_cast<T*>(act);
}
}
return nullptr;
}
Use this pattern with caution, because it limits the ability to make a class which acts exactly like another class except for specific changes. But it might be appropriate in your interface.
I am using Component Based Architecture in my application. I'm at the stage where I need to allow a Component to specify a callback that will be executed upon an event.
typedef void(Component::*EventCallback) ();
typedef std::pair<Component*, EventCallback> EventDelegate;
The problem with the above type definition is that all components inherit from Component but will never be a direct Component. So the following line of code is not valid:
MoveComponent* mc = new MoveComponent(); // inherits from Component
EventDelegate ed(mc , &MoveComponent::moveToXY); // Compiler error here: expects Component* not MoveComponent*, and same for EventCallback.
Any ideas how I can achieve a 'Polymorphic' callback? Or any other design/implementation advice?
Example usage:
typedef void(Component::*EventCallback) ();
typedef std::pair<Component*, EventCallback> EventDelegate;
class Component {
// ...
};
class MoveComponent : public Component {
public:
MoveComponent() {
EventDelegate ed(this, &MoveComponent::moveToXY);
ComponentManager::registerEvent(ed);
}
void moveToXY() { }
};
class ComponentManager {
public:
static void registerEvent(EventDelegate ed) {
evtRegistry.push_back(ed);
}
static void runEvent(EventDelegate ed) {
for (int i=0; i<evtRegistry.size(); i++) {
Component* context = evtRegistry.at(i).first;
EventCallback ec = evtRegistry.at(i).second;
context->*ec();
}
}
private:
static std::vector <EventDelegate> evtRegistry;
};
using EventDeligate = std::function<void()>;
auto cp = std::make_shared<MoveComponent>();
auto ed = EventDeligate([cp](){ cp.moveToXY(); });
To do it your way, Component must have a (possibly pure) virtual function moveToXY.
I am trying to write a class that uses DOM to write a list of Registrations to file as XML. The list of registrations contains three types of registration Registration which is the standard base registration class GuestRegistration and StudentRegistration which both derive from Registration.
The GuestRegistration class has a unique member category and the student registration has unique member qualification.
When I iterate over the list of registration pointers I only have access to the base class Registration's member functions. Is there any way I can access the subclasses' data members to use the getter functions getCategory and getQualification? I've tried creating a GuestRegistration and StudentRegistration pointer whenever the class name matches either of the two, but get a pointer conversion error.
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
QString cn = regList.at(i)->metaObject()->className();
Person tempPerson = regList.at(i)->getAttendee();
appendRegistrationAndType(cn);
appendAttendee(tempPerson);
//this is where my issue starts
if (cn == "GuestRegistration") {
GuestRegistration guestReg = regList.at(i);
appendAttendeeCatagory(guestReg.getCatagory());
}
if (cn == "StudentRegistration") {
StudentRegistration* stuReg = regList.at(i);
appendAttendeeQualification(stuReg->getQualification());
}
appendBookingDate(regList.at(i)->getBookingDate().toString());
appendRegistrationFee(regList.at(i)->calculateFee());
}
}
You can use dynamic_cast to check for specific sub-classes:
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
Registration *reg = regList.at(i);
appendRegistrationAndType(reg->metaObject()->className());
appendAttendee(reg->getAttendee());
if (GuestRegistration *guestReg = dynamic_cast<GuestRegistration*>(reg)) {
appendAttendeeCatagory(guestReg->getCatagory());
}
else
if (StudentRegistration* stuReg = dynamic_cast<StudentRegistration*>(reg)) {
appendAttendeeQualification(stuReg->getQualification());
}
// and so on ...
appendBookingDate(reg->getBookingDate().toString());
appendRegistrationFee(reg->calculateFee());
}
}
However, I would suggest implementing a virtual method in the Registration class itself that your sub-classes can override to register additional items as needed, eg:
class Registration {
...
virtual void appendExtraAttendees(RegistrationListWriter *writer){}
...
};
class GuestRegistration : public Registration {
...
virtual void appendExtraAttendees(RegistrationListWriter *writer);
...
};
void GuestRegistration::appendExtraAttendees(RegistrationListWriter *writer){
writer->appendAttendeeCatagory(getCatagory());
}
class StudentRegistration : public Registration {
...
virtual void appendExtraAttendees(RegistrationListWriter *writer);
...
};
void StudentRegistration::appendExtraAttendees(RegistrationListWriter *writer){
writer->appendAttendeeQualification(getQualification());
}
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
Registration *reg = regList.at(i);
appendRegistrationAndType(reg->metaObject()->className());
appendAttendee(reg->getAttendee());
reg->appendExtraAttendees(this);
appendBookingDate(reg->getBookingDate().toString());
appendRegistrationFee(reg->calculateFee());
}
}
Alternatively:
class Registration {
...
virtual void appendAttendees(RegistrationListWriter *writer);
...
};
void Registration::appendAttendees(RegistrationListWriter *writer){
writer->appendAttendee(getAttendee());
}
class GuestRegistration : public Registration {
...
virtual void appendAttendees(RegistrationListWriter *writer);
...
};
void GuestRegistration::appendAttendees(RegistrationListWriter *writer){
Registration::appendAttendees(writer);
writer->appendAttendeeCatagory(getCatagory());
}
class StudentRegistration : public Registration {
...
virtual void appendAttendees(RegistrationListWriter *writer);
...
};
void StudentRegistration::appendAttendees(RegistrationListWriter *writer){
Registration::appendAttendees(writer);
writer->appendAttendeeQualification(getQualification());
}
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
Registration *reg = regList.at(i);
appendRegistrationAndType(reg->metaObject()->className());
reg->appendAttendees(this);
appendBookingDate(reg->getBookingDate().toString());
appendRegistrationFee(reg->calculateFee());
}
}
The straightforward C++ tool is dynamic_cast<>().
In general it is not good practice to initially design a project that requires such cast. Various design pattern may be considered.
I see that you are using metaObject(), so it means that Registration has QObject as a base class. In that case it is possible to use qobject_cast:
The qobject_cast() function behaves similarly to the standard C++
dynamic_cast(), with the advantages that it doesn't require RTTI
support and it works across dynamic library boundaries.
Instead of using dynamic_cast, you could have the base class provide an interface that the derived classes use to write their class-specific data.
Probably you need to make the methods virtual.
Non virtual method use the methods of the class used at compile time, virtual methods of subclasses are chosen instead at runtime.
Here is my MESSAGE structure:
struct tEventMessage
{
// Type of the event
int Type;
// (void*) Allows those to be casted into per-Type objects
void *pArgument1;
void *pArgument2;
};
Can i add some kind of 'template' member to this structure, so that later on when building message i can pass those pointers + and any other data i wish ? ( see example below )
struct tEventMessage
{
// Type of the event
int Type;
// (void*) Allows those to be casted into per-Type objects
void *pArgument1;
void *pArgument2;
// Template
T tSomeTemplateMember;
};
void HandleClick(....)
{
CVector3 vNewPosition = ....
tEventMessage _msg;
_msg.Type = xxxx;
_msg.pArgument1 = pA->GetObjectPointer();
//
// Wrong!
// Because this CVector3 will not be alive in next tick
// - my pointer will point to nothing.
//
_msg.pArgument2 = static_cast<CVector3*>(&vNewPosition)
//
// Something like that would be great
// And would allow me to use CVector2,CVector3,CVector4 with one template member
//
_msg.tSomeTemplateMember = vNewPosition;
}
I think you're over complicating the problem. Instead of one problem, how to pass arbitrary data in a message, you now have two, how to cope with templates as well.
The usual method to implement this sort of thing is to use inheritance:-
class Message
{
public:
int Type () { return type; }
protected:
int type;
};
class ClickMessage : public Message
{
public:
ClickMessage () { type = ClickMessageID; }
private:
// the message data
};
void HandleMessage (Message *message)
{
switch (message->Type ())
{
case ClickMessageID:
HandleClick (reinterpret_cast <ClickMessage *> (message));
break;
default:
// unhandled message error
break;
}
}
void HandleClick (ClickMessage *message)
{
// do stuff
}
The problem is you end up repeating a lot of code, i.e the cast in the switch statement. There's also a maintenance issue too - added new messages requires a bit of careful updating. You could hack the code a bit and use function pointers and a map to convert message types to functions and replace the switch statement.
There might be a clever template solution, but I can't think what it might be.
Using RTTI might help (at a cost).
This is one problem that reflection is really good at solving!
Perhaps I am missing something however I am wondering why you do not start with an abstract class from which you then derive your various kinds of event messages. By taking advantage of abstract classes and deriving classes from them, you let the compiler figure out the logic that you are using a switch statement for. See this C++ Polymorphism and Abstract Base Class tutorial.
Also see this from MSDN on Abstract classes.
For instance you might have an abstract class that looks like the following. However you may not want as much of this and in fact may just want the single processEvent() method only. Any derived classes will need to provide their own versions of each of the functions specified in the abstract class.
class EventMessage abstract {
public:
virtual void *getArgument1 (void) = 0;
virtual void *getArgument2 (void) = 0;
virtual int processEvent (void) = 0;
protected:
void *pArgument1;
void *pArgument2;
};
What this abstract class defines is a class that basically contains the data that is used by all of the various event messages along with a method that is called to process the the actual message. The class itself is not instantiated however it is used as the parent or super class for other derived class that are actually instantiated as objects.
What you would then do is to derive new classes that would implement the EventMessage interface. For instance here are two different classes that would do that:
class JoJoEvent : public EventMessage {
public:
JoJoEvent(void *arg1, void *arg2);
void *getArgument1 (void);
void *getArgument2 (void);
int processEvent (void);
};
JoJoEvent::JoJoEvent(void *arg1, void *arg2)
{
pArgument1 = arg1;
pArgument2 = arg2;
}
void * JoJoEvent::getArgument1 (void) {
return pArgument1;
}
void * JoJoEvent::getArgument2 (void) {
return pArgument2;
}
int JoJoEvent::processEvent (void) {
// do stuff with the arguments
return 1;
}
class KoKoEvent : public EventMessage {
public:
KoKoEvent(void *arg1, void *arg2);
void *getArgument1 (void);
void *getArgument2 (void);
int processEvent (void);
};
KoKoEvent::KoKoEvent(void *arg1, void *arg2)
{
pArgument1 = arg1;
pArgument2 = arg2;
}
void * KoKoEvent::getArgument1 (void) {
return pArgument1;
}
void * KoKoEvent::getArgument2 (void) {
return pArgument2;
}
int KoKoEvent::processEvent (void) {
// do stuff with the arguments
return 1;
}
Then when using these you would do something like the following code:
EventMessage *myMessage = new JoJoEvent(0, 0);
EventMessage *myMessage2 = new KoKoEvent(0, 0);
myMessage2->processEvent();
myMessage->processEvent();
If you need to add additional data into the derived classes you can do so just provide a mechanism to put the data into the derived class.