Is there a way to cast base class to derived, calling default constructor? I'm receiving network data, writing it to packets, then calling protocol function which I wish to parse data differently.
class BasePacket {
protected:
std::vector<char> data;
public:
BasePacket(){data.reserve(2048);}
BasePacket(char* _data, int len){ data.assign(&data[0], &data[len]); }
};
class ActionPacket : public BasePacket {
public:
char Action;
char Job;
ActionPacket(){
Action = data[0];
Job = data[1];
}
};
I would like to do something like:
void ProcessPacket(BasePacket& packet){
if (packet.data[0] == 1){
auto t = (ActionPacket)packet;
if(t.Job == 1){
//dosmth
}
}
if (packet.data[0] == 2){
auto t = (OtherPacket)packet;
if(t.smth){
//do another smth
}
}
}
CodePudding user response:
If your instance is initially a BasePacket
object, why not just code like ActionPacket::ActionPacket(BasePacket&)
? That's because ActionPacket
have some members that BasePacket
doesn't have, reallocation seems inevitable. Just like this:
class ActionPacket
{
ActionPacket(BasePacket& basePacket) :BasePacket(basePacket), Action(data[0]), Job(data[1]) {};
};
// assuming there is a legal BasePacket object called basePacket
auto actionPacket = ActionPacket{basePacket};
BUT, if you are sure that this BasePacket
object will ONLY be used for constructing ActionPacket
here and will never be used afterwards, you can write ActionPacket::ActionPacket(BasePacket&&)
and use std::move
like this:
class ActionPacket
{
ActionPacket(BasePacket&& basePacket) :BasePacket(std::move(basePacket)), Action(data[0]), Job(data[1]) {};
};
// assuming there is a legal BasePacket object called basePacket
auto actionPacket = ActionPacket{std::move(basePacket)};
This will be more efficient since std::vector
is moved but not re-constructed.
If your instance is initially an ActionPacket
object, and there are no virtual methods, static_cast
is acceptable; But if there are some virtual methods, dynamic_cast
is what you want.