S
Spoon
Hello everyone,
I'm writing code where I can receive two kinds of packets.
The first 12 octets are common to both packet types, i.e. they have
the same semantics.
The 1st type has 4 more octets in the header, then the payload.
The 2nd type has 16 more octets in the header, then the payload.
I was thinking I'd write a base class with two derived classes:
class BasePacket {
public:
BasePacket(uint8_t *buf, int size)
{ allocate memory and copy buf to buffer }
virtual uint8_t *Payload() = 0;
int type() { return buffer[1]; }
private:
uint8_t *buffer;
};
class Type1_Packet : public BasePacket {
public:
/* No constructor for this class -- see below */
virtual uint8_t *Payload() { return buffer + 12 + 4; }
+ access functions to the additional header parts
}
class Type2_Packet : public BasePacket {
public:
/* No constructor for this class -- see below */
virtual uint8_t *Payload() { return buffer + 12 + 16; }
+ access functions to the additional header parts
}
And my intention was to write a function that would listen on
several sockets and return a true BasePacket *
BasePacket *the_listener()
{
...
return new BasePacket(somebuf, somesize);
}
Is it safe to then write:
BasePacket *packet = the_listener();
if (packet->type() == XX)
{
/* we know the packet is in fact a Type1_Packet */
Type1_Packet *foo = <some_kind_of_cast> packet;
do something with foo;
foo->Payload() would return buffer+16
}
else if (packet->type() == YY)
{
/* we know the packet is in fact a Type2_Packet */
Type2_Packet *foo = <some_kind_of_cast> packet;
do something with foo;
foo->Payload() would return buffer+28
}
In other words, is it safe to cast a true BasePacket * into a pointer to
one of the derived objects? (Given that the derived classes have no
additional members.)
Another way I've considered is:
class BaseClass
{
public:
BaseClass(int a) : toto(a) { }
private:
int toto;
};
class Derived1 : public BaseClass
{
public:
Derived1(double x) : BaseClass(123), tutu(x) { }
private:
double tutu;
};
class Derived2 : public BaseClass
{
public:
Derived2(long x) : BaseClass(456), zozo(x) { }
private:
long zozo;
};
#include <list>
void add_to_list(int i, std::list<BaseClass *> queue)
{
if (i)
{
Derived1 *toto = new Derived1(3.1416);
queue.push_back(toto);
}
else
{
Derived2 *toto = new Derived2(987654);
queue.push_back(toto);
}
}
int main()
{
std::list<Derived1 *> q1;
add_to_list(1, q1);
return 0;
}
But that doesn't work either.
Otherwise, I imagine there is a better way to do what I want to do.
Regards.
I'm writing code where I can receive two kinds of packets.
The first 12 octets are common to both packet types, i.e. they have
the same semantics.
The 1st type has 4 more octets in the header, then the payload.
The 2nd type has 16 more octets in the header, then the payload.
I was thinking I'd write a base class with two derived classes:
class BasePacket {
public:
BasePacket(uint8_t *buf, int size)
{ allocate memory and copy buf to buffer }
virtual uint8_t *Payload() = 0;
int type() { return buffer[1]; }
private:
uint8_t *buffer;
};
class Type1_Packet : public BasePacket {
public:
/* No constructor for this class -- see below */
virtual uint8_t *Payload() { return buffer + 12 + 4; }
+ access functions to the additional header parts
}
class Type2_Packet : public BasePacket {
public:
/* No constructor for this class -- see below */
virtual uint8_t *Payload() { return buffer + 12 + 16; }
+ access functions to the additional header parts
}
And my intention was to write a function that would listen on
several sockets and return a true BasePacket *
BasePacket *the_listener()
{
...
return new BasePacket(somebuf, somesize);
}
Is it safe to then write:
BasePacket *packet = the_listener();
if (packet->type() == XX)
{
/* we know the packet is in fact a Type1_Packet */
Type1_Packet *foo = <some_kind_of_cast> packet;
do something with foo;
foo->Payload() would return buffer+16
}
else if (packet->type() == YY)
{
/* we know the packet is in fact a Type2_Packet */
Type2_Packet *foo = <some_kind_of_cast> packet;
do something with foo;
foo->Payload() would return buffer+28
}
In other words, is it safe to cast a true BasePacket * into a pointer to
one of the derived objects? (Given that the derived classes have no
additional members.)
Another way I've considered is:
class BaseClass
{
public:
BaseClass(int a) : toto(a) { }
private:
int toto;
};
class Derived1 : public BaseClass
{
public:
Derived1(double x) : BaseClass(123), tutu(x) { }
private:
double tutu;
};
class Derived2 : public BaseClass
{
public:
Derived2(long x) : BaseClass(456), zozo(x) { }
private:
long zozo;
};
#include <list>
void add_to_list(int i, std::list<BaseClass *> queue)
{
if (i)
{
Derived1 *toto = new Derived1(3.1416);
queue.push_back(toto);
}
else
{
Derived2 *toto = new Derived2(987654);
queue.push_back(toto);
}
}
int main()
{
std::list<Derived1 *> q1;
add_to_list(1, q1);
return 0;
}
But that doesn't work either.
Otherwise, I imagine there is a better way to do what I want to do.
Regards.