Calling a derived class method from the parent class' same method - c++

My problem goes as follow: I am writing an extensible communication protocol between a server and a client. The objects needed to be transferred are using the command design pattern.
Here is the class format:
class command {
public:
using id = uint8_t;
using buffer = std::vector<char>;
enum command_t: id {a_command, another_command};
command() = delete;
command(id id): id_(id) {}
static command* unserialize(buffer);
virtual buffer const serialize() const = 0;
virtual void execute() = 0;
protected:
/* Not possible, see further where I explain. Keeping it here for
my example */
virtual static command* do_unserialize(buffer::iterator, buffer::iterator) = 0;
id id_;
};
class a_command;
class another_command;
Every command will be a subclass of command. A command_t id will be associated with every command. In the example above, a_command and another_command would have a respective class too.
command::serialize is implemented in the derived classes. What it does is it writes all the needed informations of the class in a byte array and returns it. Of course, the same thing goes for the protected command::do_unserialize - it takes a byte array and converts it to a command of the right type. But here is the problem:
The first byte of the buffer will always be the command::id associated with the good subclass.
When the server/client will receive data, it will read the command ID and then it needs to be able to unserialize it to the right command type. This is why it will need to call the static function command::unserialize and not one of the subclasses' do_unserialize.
A quick and dirty fix would be a command::unserialize looking like this:
command* command::unserialize(buffer b) {
auto it{b.begin()};
command::id const id{*it++};
switch(static_cast<command::command_t>(id)) {
case command::command_t::a_command:
return a_command::do_unserialize(it, b.end());
case command::command_t::another_command:
return another_command::do_unserialize(it, b.end());
default:
throw std::invalid_argument("command::unserialize: unknown command ID");
}
}
*** Actually not even, you cannot have a virtual static member function. So I have no idea how it could be implemented.
Even if it worked, it is not really fun, because it implies having to duplicate a line of code
for every new command created.
EDIT: A working example would be to move do_unserialize to the subclass constructor and return a pointer to the newly created object.
class derived_command: public command {
public:
derived_command(buffer::iterator beg, buffer::iterator end) {
// do_unserialize logic
}
};
// unserialize
switch (id) {
case command::command_t::derived_class: return new derived_class(b.begin(), b.end());
}
// ...
My question thus goes like this: Is there a way to dynamically link new commands only from the command::id field? A way to deduce the subclass to use from its ID? Else, is my design flawed? Is there a better way to do what I'm trying to do?
Thank you!

Related

Creating Command objects at run-time

I'm trying to write a console for a game engine which will allow me to type in commands to perform tasks, such as change the map, spawn an enemy etc.
I've been trying to do this with the Command pattern (following the example from gameprogrammingpatterns.com). See below for the outline of my current code structure.
parseCommand processes the string from the user, extracting the command name and arguments (currently using just whitespace separation). The next step is where I'm stuck. I need to create a Command* somehow to call execute on but I only have the string name of the command.
I could have a giant bunch of if statements in my parseCommand function, such as:
if (cmdName == "spawn")
return new SpawnEnemyCommand();
Alternatively I could store a pointer to each command in myConsole class, e.g. Command *spawnNewEnemy = new SpawnNewEnemy(); and then in parseCommand do if (cmdName == "spawn") spawnNewEnemy->execute();. This second option seems to be how the gameprogrammingpatterns book does it.
Neither of these options seems very practical if I end up with hundreds of console commands. I've studied all the articles and posts I can find on this pattern but it isn't helping clarify the situation for me.
How can I cleanly instantiate the correct Command object from within parseCommand?
Command interface base class:
class Command {
public:
virtual ~Command() { }
virtual void execute() = 0;
};
Example interface implementation:
class SpawnEnemyCommand : public Command {
public:
void execute() {
// method calls to perform command go here
}
};
Console class header:
class Console {
public:
Command* parseCommand(std::string);
bool validateCommand(std::string, std::vector<std::string>);
};
By relying on a dictionary (e.g, std::unordered_map or std::map) that maps a command identifier (i.e., a std::string object) to a Command object, you can design a factory with dynamic registry for your Command objects.
First, extend Command by including another virtual member function, clone(), that allows us to implement The Prototype Pattern:
class Command {
public:
// ...
virtual std::unique_ptr<Command> clone() const = 0;
};
The clone() virtual member function does what its name suggests: it clones the object. That is, SpawnEnemyCommand would override Command::clone() in the following way:
class SpawnEnemyCommand : public Command {
public:
// ...
std::unique_ptr<Command> clone() const override {
// simply create a copy of itself
return std::make_unique<SpawnEnemyCommand>(*this);
}
};
This way, your command objects can be copied polymorphically through the Command interface – i.e., you don't need to know the concrete type of the command to be copied. All you need to do to copy a Command object is to call its clone() virtual member function. For example, the following function copies the Command passed as an argument regardless of the underlying concrete type:
std::unique_ptr<Command> CopyCommand(const Command& cmd) {
return cmd.clone();
}
With this in mind, you are ready to design a factory for command objects, CommandFactory, that supports dynamically registering your command objects:
class CommandFactory {
public:
void registerCommand(std::string id, std::unique_ptr<Command>);
std::unique_ptr<Command> createCommand(std::string id) const;
private:
std::unordered_map<std::string, std::unique_ptr<Command>> registry_;
};
It all boils down to a std::unordered_map<std::string, std::unique_ptr<Command>> data member. Indexing this data member by a command identifier, which is an std::string, we retrieve a Command object – This is the prototype object we will use for cloning.
The registerCommand() member function adds a Command prototype to the registry:
void CommandFactory::registerCommand(std::string cmdId, std::unique_ptr<Command> cmd) {
registry_[cmdId] = std::move(cmd);
}
The createCommand() member function clones the Command prototype corresponding to the requested command identifier:
std::unique_ptr<Command> CommandFactory::createCommand(std::string cmdId) const {
auto const it = registry_.find(cmdId);
if (it == registry_.end())
return nullptr; // no such a command in the registry
auto const& cmdPtr = it->second;
return cmdPtr->clone();
}
As an example program:
auto main() -> int {
CommandFactory factory;
factory.registerCommand("spawn", std::make_unique<SpawnEnemyCommand>());
// ...
auto cmdPtr = factory.createCommand("spawn");
cmdPtr->execute();
}
You can also extend this factory to add support for dynamically deregistering your already-registered Command prototypes.

C++ can't access field from inherited class

Hello guys a have a problem, that i can't access field tablica[i]->help, in generuj function, its saying that this field is not existing in class Task.
How can i achieve it ?
class Task
{
protected:
string contents;
int id_pyt;
int nr_pyt;
};
class Task4Answ : public Task
{
private:
int help;
public:
Task4Answ(string contents1, int id,int nr,int help1)
{
contents=contents1;
id_pyt=id;
nr_pyt=nr;
help=help1;
}
};
class TaskCollection
{
protected:
Task *collection[60];
public:
friend class Generator;
TaskCollection()
{
collection[0] = new Task4Answ("Ile jest por roku w Polsce? \na) 1 \nb) 2 \nc) 3 \nd) 4",1,0);
collection[1] = new Task4Answ("Kto wygral tegoroczny Roland Garros? \na) Federer \nb) Djokovic \nc) Nadal \nd) Thiem",1,1);
class Generator
{
protected:
Task *tablica[10];
TaskCollection T1;
public:
Generator(){}
void Generuj()
{
if(T1.collection[x]->id_pyt==1)
{
tablica[i]=new Task4Answ("0",0,0);
tablica[i]->contents=T1.collection[x]->contents;
tablica[i]->id_pyt=T1.collection[x]->id_pyt;
tablica[i]->nr_pyt=T1.collection[x]->nr_pyt;
tablica[i]->help=T1.collection[x]->help; //here is the problem
}
}
}
Or maybe there is some other solution of the project im doing now.
Thanks for any help.
The problem is in this line:
tablica[i]=new Task4Answ("0",0,0);
Although you have called the Task4Answ constructor, you are also assigning the memory address returned by new to a Task pointer. Effectively, you have casted the Task4Answ pointer to a Task pointer. On the lines that follow, C++ only sees tablica[i] as a reference to a Task pointer. You need to change:
protected:
Task *tablica[10];
TaskCollection T1;
...to this:
protected:
Task4Answ *tablica[10]; // Task was changed to Task4Answ
TaskCollection T1;
That should allow C++ to see tablica as an array of Task4Answ pointers instead of Task pointers.
Edit: it looks like help is also private. You will have to change help to public or add TaskCollection::TaskCollection() as a friend. Otherwise, C++ will not let you get or set help.
Edit: the OP added that tablica[i] might contain instances of other classes that inherit from Task. In that case, you could do something like this:
void Generuj()
{
if(T1.collection[x]->id_pyt==1)
{
Task4Answ* newTask = new Task4Answ("0",0,0);
newTask->contents=T1.collection[x]->contents;
newTask->id_pyt=T1.collection[x]->id_pyt;
newTask->nr_pyt=T1.collection[x]->nr_pyt;
newTask->help=T1.collection[x]->help; // You will still have to change this from being private.
tablica[i] = newTask;
}
}
}
Later on, in order to access help, you will need to implement some sort of way of checking whether tablica[i] is a Task4Answ and not an instance of some other class that inherits from Task, perhaps by implementing a method in Task named IsTask4Answ that returns false in Task but is overridden to return True in Task4Answ. You can then cast the pointer back to Task4Answ with something like the static_cast operator. In other words:
// Add these functions to the class definitions:
virtual bool Task::IsTask4Answ() const {
return false;
}
bool Task4Answ::IsTask4Answ() const override {
return true;
}
// Later, you can do this:
if(tablica[i].IsTask4Answ()){
Task4Answ* t = static_cast<Task4Answ*>(tablica[i]);
t->help; // Again, you'll have to change this from being private.
}
Although I suggest figuring out a different data structure where you do not need to do any casting, this will allow you to access help.
Do note the virtual keyword in the first function above; it allows the function to be dynamically bound, which means that the code will check whether to call Task::IsTask4Answ() or Task4Answ::IsTask4Answ() at runtime instead of at compile time.

Best way to change from base class to derived class

I know this is asked in various ways on this forum, but I still can't quite figure out the best way to go about what I need to do (after reading various other posts). So I have decided to seek further advice!
I have a message class hierarchy, something like (omitted most details):
class MsgBase
{
public:
uint8_t getMsgType(void);
protected: // So that derived classes can access the member
char _theMsgData[100];
}
class MsgType1 : public MsgBase
{
}
class MsgType2 : public MsgBase
{
}
So what happens is I received a block of message data and I use it to create my message. But I don't know which message to create until I read out the message type. So I end up with:
MsgBase rxMsg(rxData);
if (rxMsg.getMsgType() == 1)
{
// Then make it a MsgType1 type message
}
else if (rxMsg.getMsgType() == 2)
{
// Then make it a MsgType2 type message
}
This is the bit I am stuck on. From what I have read, I cannot dynamical cast from base to derived. So my current option is to instantiate a whole new derived type (which seems inefficient), i.e.:
if (rxMsg.getMsgType() == 1)
{
// Now use the same data to make a MsgType1 message.
MsgType1 rxMsg(rxData);
}
Is there a way that I can look at the data as the base class so that I can determine its type and then "molymorph" it into the required derived type?
Thanks,
Fodder
What is rxData? I assume it's just a blob of data, and you should parse it to determine the message type before you create any message object. And depending on if the message data has always the same length you should consider using std::array or std::vector to pass the data blob around.
typedef std::vector<char> MsgDataBlob;
class MsgBase
{
public:
uint8_t getMsgType();
MsgBase(MsgDataBlob blob) : _theMsgData(std::move(blob)) {}
protected: // So that derived classes can access the member
MsgDataBlob _theMsgData;
};
//derived classes here...
//this could be either a free function or a static member function of MsgBase:
uint8_t getMessageType(MsgDataBlob const& blob) {
// read out the type from blob
}
std::unique_ptr<MsgBase> createMessage(MsgDataBlob blob) {
uint8_t msgType = getMessageType(blob);
switch(msgType) {
case 1: return make_unique<MsgDerived1>(std::move(blob));
case 2: return make_unique<MsgDerived2>(std::move(blob));
//etc.
}
}
If you want the messages to return the data, but for example MsgType1 should make it all lower case, and MsgTyp2 all upper case you could make a virtual function in MsgBase called, for example,
virtual char *getData();
and this function should be reimplemented in child classes so that it does with the data what you want it to do. This way when you call this function on base class pointer, you will get reimplemented functionality, depending to what type the actual pointer is, at the moment of calling.

A proper way to restrict access to an interface?

Let's say I have a class that represents a printing job: CPrintingJob. It knows nothing of the document being printed, just the job state - whether the job was queued, rejected, carried on etc.
The idea is an object of this class is instantiated whenever some printing needs to be done, then passed to the printing module along with other data, then the job's creator checks its state to see how printing is going.
Suppose CPrintingJob inherits two interfaces:
class IPrintingJob // this one is to check the job state
{
virtual TState GetState() const = 0;
// ... some other state-inquiring methods
class ICallback // job's owner is notified of state changes via this one
{
virtual void OnStateChange( const IPrintingJob& Job ) = 0;
};
};
and
class IPrintingJobControl // this one is for printing module to update the state
{
virtual void SetState( const TState& NewState ) = 0;
// ... some other state-changing methods
};
Problem is, the class that creates a CPrintingJob object shouldn't have access to the IPrintingJobControl, but the printing module CPrintingJob is being passed to must be able to change its state and, therefore, have access to that interface.
I suppose this is exactly the case where friends should be used but I have always avoided them as an inherently flawed mechanic and consequently have no idea of how to use them properly.
So, how do I do it properly?
Use a factory and have the factory return an instance of IPrintingJob (best wrapped inside a smart_ptr). e.g.:
struct PrintingFactory {
static auto create() -> std::unique_ptr<IPrintingJob> {
return std::unique_ptr<IPrintingJob>(new CPrintingJob());//as there is currently no std::make_unique..
}
}
Once you have to use the JobControl you can simply cast the pointer via std::dynamic_pointer_cast.
After some deliberation I've decided that:
This whole thing is definitely more trouble than it's worth;
(A slightly modified) version of MFH's answer above is the only, hence the best, way to go.
Thanks everyone for the input, it certainly has been enlightening.

What's a good safe way to initialise memory for types I don't yet know about?

I started thinking about this after receiving an answer for this question. This is a bit tricky to explain, but I'll do my best.
I'm building a small(ish) 2D game engine. There are certain requirements that I need to satisfy, since this engine has to "work" with existing code that others have written for a different engine. Some change to existing code is inevitable, but I want to minimise it.
Users of my engine need to define entities called "gadgets". These are basically structs containing shapes and other state variables. These "gadgets" fall into classes, e.g. they may decide to define an icon gadget or a button gadget - or whatever.
They will also define a message handler for that class of gadgets.
E.g.
typedef struct
{
shape shapelist[5];
int num_options;
}interface;
static void interface_message_handler( interface * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
....
}
}
Users have already given me the corresponding message handler function and also the number of bytes in a interface object. And they can then ask the engine to create new instances of their gadgets via IDs e.g:
engine->CreateNewGadget( interface_gadget_class_ID, welcome_interface_ID );
where interface_gadget_class_ID is the ID for that class of gadgets and welcome_interface_ID is the instance ID. At some point during CreateNewGadget I need to a) allocate memory to hold a new gadget and then call the gadget class's message handler on it, with a NEW_MSG so that it can initialize itself.
The problem is, if all I'm doing is allocating memory - that memory is uninitialized (and that means all the struct members are uninitialized - so if interface contains a vector, for example, then I'm going to get some wierd results if the message handler does anything with it ).
To avoid wierd results caused by doing stuff to unintialized memory, I really need to call a constructor for that memory as well before passing it to the gadget's message handler function.
e.g in the case of interface:
pfunc(new (memory) interface);
But my question is, if I have no knowledge of the types that users are creating, how can I do that?
// We create a typedef that refers to a function pointer
// which is a function that returns an interface pointer
typedef interface * (*GadgetFactory)(void);
// we'll actually create these functions by using this template function
// Different version of this function will produce different classes.
template<typename T>
interface * create_object()
{
return new T;
}
// This function takes care of setting everything up.
template<typename T>
void RegisterGadgetType(int gadget_type_id)
{
// Get outselves a copy of a pointer to the function that will make the object
GadgetFactory factory = create_object<T>;
// store factory somewhere
}
interface * CreateGadget(int gadget_type_id)
{
// get factory
GadgetFactory factory;
// factory will give me the actual object type I need.
return (*factory)();
}
RegisterGadgetType<S>(2);
CreateGadget(2);
as i see it, you always know because interface_gadget_class_ID defines the type to create.
you create a base c++ class: (corresponds to class interface in your example). this base class contains all of data members which are used by every interface subclass (that is, every gadget).
the base class also declares all methods common to every gadget. example: each gadget is able to receive a call handleMessage. handleMessage is pure virtual, because this method is the subclasses' role to fulfill.
then you extend/subclass to support the stuff you have to do with each gadget's specialization. at this point, you add the members and methods specific to each gadget subclass.
CreateNewGadget serves as a factory for all your subclasses, where the arguments determine which class you will create.
from there, c++ will handle construction/destruction, allocation sizes, etc..
if you're allowing plugins with their own factories in your engine, then you'll need another level, where third parties register their custom types and inherit from your base(s).
here's a simple layout of the interfaces (in non-compiled pseudo code):
namespace MONGadgets {
class t_interface {
protected:
t_interface(/* ... */);
public:
virtual ~t_interface();
/* each subclass must override handleMessage */
virtual t_result handleMessage(const t_message& message) = 0;
};
namespace InterfaceSubclasses {
class t_gadget1 : public t_interface {
public:
t_gadget1(const welcome_interface_ID& welcome);
virtual ~t_gadget1();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget1\n";
}
/* gadget1 has no specific instance variables or methods to declare */
};
class t_gadget2 : public t_interface {
public:
t_gadget2(const welcome_interface_ID& welcome);
virtual ~t_gadget2();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget2\n";
}
private:
/* here is an example of a method specific to gadget2: */
void drawShape(const unsigned& idx);
private:
/* here is gadget2's unique data: */
shape shapelist[5];
int num_options;
};
namespace ClassID {
enum { Gadget1 = 1, Gadget2 = 2 };
}
}
/* replaced by virtual t_result t_interface::handleMessage(const t_message&)
- static void interface_message_handler( interface * myself, message * msg );
*/
class t_gadget_factory {
public:
t_interface* CreateNewGadget(const interface_gadget_class_ID& classID, const welcome_interface_ID& welcome) {
switch (classID) {
case InterfaceSubclasses::ClassID::Gadget1 :
return new InterfaceSubclasses::gadget1(welcome);
case InterfaceSubclasses::ClassID::Gadget2 :
return new InterfaceSubclasses::gadget2(welcome);
/* ... */
}
}
};
}
Example code (ignoring my other suggestion, about factories and virtual functions):
typedef struct
{
shape shapelist[5];
int num_options;
} interface;
static void interface_message_handler( void * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface *self = new (myself) interface;
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
case OTHER_MSG:
{
interface *self = static_cast<interface*>(myself);
...
}
break;
....
}
}
Then your CreateNewGadget code does:
void *ptr = malloc(some_amount);
msg newmsg;
newmsg.type = NEW_MSG;
// other fields
some_message_handler(ptr, &msg);
// now we have an initialized object, that we can add to our tree or whatever.
The less horrible version is more like this:
struct gadgetinterface {
virtual ~gadgetinterface() {}
virtual void handle_message(msg *) = 0;
};
struct mygadget : gadgetinterface {
void handle_message(msg *m) {
// no need for NEW_MSG, just do other messages
}
};
gadgetinterface *mygadget_factory(some parameters) {
// use some parameters, either passed to constructor or afterwards
return new mygadget();
}
Then we register a pointer to mygadget_factory with the gadget manager, and CreateNewGadget does this:
gadgetinterface *some_factory(some parameters); // that's it!
Where some_factory is the function pointer that was registered, so in the case of this gadget type, it points to mygadget_factory.