|
-
August 31st, 2009, 07:44 PM
#1
class size changes when inheriting abstract ones...
Hello guys, I'm writing a network library to use in the future on my projects, but I got something that I don't know why is happens...
------------------------------------------------------------------------------------
// IocpServer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
// Struct to store the serialized information
struct SerializedBuffer
{
void* Buffer;
unsigned int Size;
};
class ISerializable
{
public:
virtual unsigned int SerializedSize() = 0;
virtual void Serialize(SerializedBuffer& mBuffer) = 0;
};
/*####################################*/
// This is the packet interface... all packets sent over the network must have this as base
class IPacket
: public ISerializable
{
public:
virtual unsigned int GetProtocolType() = 0;
virtual unsigned int GetProtocolAction() = 0;
virtual unsigned int GetPacketSize() = 0;
virtual unsigned int SerializedSize() = 0;
virtual void Serialize(SerializedBuffer& mBuffer) = 0;
};
/*####################################*/
#pragma pack(push, 1)
class DefaultPacket
: public IPacket
{
private:
unsigned short m_wSize; // Returned by the GetPacketSize(); on its implementation
unsigned short m_wActionType; // Returned by the GetProtocolType(); on its implementation
unsigned short m_wActionIndex; // Returned by the GetProtocolAction(); on its implementation
public:
DefaultPacket(unsigned short wActionType = 0, unsigned short wAction = 0)
{
this->m_wSize = 0;
this->m_wActionType = wActionType;
this->m_wActionIndex = wAction;
}
~DefaultPacket(void)
{
}
unsigned int GetProtocolType()
{
return this->m_wActionType;
}
unsigned int GetProtocolAction()
{
return this->m_wActionIndex;
}
unsigned int GetPacketSize()
{
return this->m_wSize;
}
virtual unsigned int SerializedSize() = 0; // from ISerializable - must be implemented on the final derived class
virtual void Serialize(SerializedBuffer& mBuffer) = 0; // from ISerializable - must be implemented on the final derived class
};
/*####################################*/
class MyAction1
: public DefaultPacket
{
private:
unsigned int MyDataAsNumber;
public:
MyAction1()
: DefaultPacket(0, 1) // Action 0, SubAction 1
{
}
~MyAction1()
{
}
unsigned int SerializedSize()
{
this->m_wSize = sizeof(*this);
return sizeof(*this);
}
void Serialize(SerializedBuffer& mBuffer)
{
mBuffer.Size = this->SerializedSize();
mBuffer.Buffer = this;
}
};
#pragma pack(pop, 1)
int _tmain(int argc, _TCHAR* argv[])
{
// why it displays 10 since I'm using pack() and 3 short vars? why not 6?
printf("sizeof(DefaultPacket) : %d\n", sizeof(DefaultPacket));
// 10 + dword = 14... but i was expecting 10, 4 bytes appeared from nowhere
printf("sizeof(MyAction1) : %d\n", sizeof(MyAction1));
system("pause");
return 0;
}
------------------------------------------------------------------------------------
OBS: Look at the code comments
-
September 1st, 2009, 12:13 AM
#2
Re: class size changes when inheriting abstract ones...
-
September 1st, 2009, 01:10 AM
#3
Re: class size changes when inheriting abstract ones...
Classes don't have a size you can use... they are NOT structures.
DON'T do this:
Code:
return sizeof(*this);
Last edited by Skizmo; September 1st, 2009 at 01:13 AM.
-
September 1st, 2009, 04:14 AM
#4
Re: class size changes when inheriting abstract ones...
 Originally Posted by wolfulus
int _tmain(int argc, _TCHAR* argv[])
{
// why it displays 10 since I'm using pack() and 3 short vars? why not 6?
printf("sizeof(DefaultPacket) : %d\n", sizeof(DefaultPacket));
// 10 + dword = 14... but i was expecting 10, 4 bytes appeared from nowhere
printf("sizeof(MyAction1) : %d\n", sizeof(MyAction1));
You shouldn't need to know the sizeof() those classes. The classes you are using are non-POD. The size of a non-POD type is useless to you and what you're trying to do.
So trying to figure out what the sizeof() a non-POD type iis indicates you're program is doing something incorrect in terms of design and approach. The one reason to try and figure out the sizeof() a non-POD type is to use placement-new or equivalent, and your program is not doing that.
So you need to go back to the beginning and come up with a different strategy altogether. The sizeof() approach isn't going to work.
Regards,
Paul McKenzie
-
September 1st, 2009, 04:19 AM
#5
Re: class size changes when inheriting abstract ones...
 Originally Posted by Skizmo
Classes don't have a size you can use... they are NOT structures.
DON'T do this:
Code:
return sizeof(*this);
Actually classes and structs are the same thing with just minor differences in default access specifiers. You can have POD classes and structs,
Just to clarify, you mean that the sizeof(*this), where *this is a non-POD type is really useless in the OP's situation. Even if the class/struct is POD, I would advise against using sizeof() as a part of any real program that is designed to serialize data. Too many things can go wrong when the sizeof() a struct/class is used as the basis for serialization, saving data, etc.
Regards,
Paul McKenzie
-
September 1st, 2009, 04:27 AM
#6
Re: class size changes when inheriting abstract ones...
Actually classes and structs are the same thing with just minor differences in default access specifiers. You can have POD classes and structs,
Yeah.. after reading your post about the POD type I realized that that was what I meant
-
September 1st, 2009, 11:20 AM
#7
Re: class size changes when inheriting abstract ones...
thanks for the comments guys... i'm really new to c++... so there is there any other method to know the size to use? coz it must be sent in the packet for splitting data that comes to the server (or client), then the server with reverse the "serialized" data to a new instance of the class and then dispatch it to the protocol function table by its action & subaction
it works fine with structs, but i want to make it more "dynamic"... any suggestions?
thanks
-
September 1st, 2009, 11:28 AM
#8
Re: class size changes when inheriting abstract ones...
What I'd do is just write an operator>> and operator<< for the class. If you can print out to the console all of the necessary data to reconstruct the object, and read it back in using the same format, then you can do the same thing to a memory buffer for serialization.
There is the Boost.Serialization library, but that's probably going to be too advanced for you to worry about now.
-
September 2nd, 2009, 02:06 PM
#9
Re: class size changes when inheriting abstract ones...
thank you guys, i rewrited it, now the "final" idea implementation:
----------------------------
Code:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
/*
Self-explainable
*/
struct SerializedBuffer
{
void* Buffer;
unsigned int Size;
};
/*
To send it over the network
*/
class __declspec(novtable) ISerializable
{
public:
virtual unsigned int SerializedSize() = 0;
virtual void Serialize(SerializedBuffer& mBuffer) = 0;
};
/*
Interface for packets, allowing different types of "packet structures"
*/
class __declspec(novtable) IPacket
: public ISerializable
{
public:
virtual unsigned int GetProtocolType() = 0;
virtual unsigned int GetProtocolAction() = 0;
virtual unsigned int GetPacketSize() = 0;
virtual unsigned int SerializedSize() = 0;
virtual void Serialize(SerializedBuffer& mBuffer) = 0;
};
#pragma pack(push, 1) // No garbage please, this types are just for communication!
/*
Information for knowing which function to call for parsing the packet
*/
union DefaultPacketAction
{
unsigned int FullIndex;
struct
{
unsigned short Type;
unsigned short Index;
} Identity;
};
/*
Packet Header for splitting & processing data on the protocol core
*/
struct DefaultPacketHeader
{
unsigned short Size;
DefaultPacketAction Action;
};
template<class DataType>
class DefaultPacket
: public IPacket
{
protected:
DefaultPacketHeader m_Header;
DataType m_Data;
public:
DefaultPacket(unsigned short wActionType = 0, unsigned short wActionIndex = 0)
{
this->m_Header.Size = sizeof(DefaultPacketHeader) + sizeof(DataType);
this->m_Header.Action.Identity.Type = wActionType;
this->m_Header.Action.Identity.Index = wActionIndex;
ZeroMemory(&this->m_Data, sizeof(DataType));
}
~DefaultPacket(void)
{
}
DataType* operator -> ()
{
return &this->m_Data;
}
unsigned int GetProtocolType()
{
return this->m_Header.Action.Identity.Type;
}
unsigned int GetProtocolAction()
{
return this->m_Header.Action.Identity.Index;
}
unsigned int GetPacketSize()
{
return this->m_Header.Size;
}
virtual unsigned int SerializedSize()
{
this->m_Header.Size = sizeof(DefaultPacketHeader) + sizeof(DataType);
return this->m_Header.Size;
}
virtual void Serialize(SerializedBuffer& rBuffer)
{
rBuffer.Buffer = &this->m_Header;
rBuffer.Size = this->SerializedSize();
}
};
struct MyAction1
{
unsigned int MyData1;
unsigned short MyData2;
char MyData3[10];
};
#pragma pack(pop, 1) // No garbage please, this types are just for communication!
void DisplayHex(unsigned char* Buffer, unsigned int Length)
{
for(unsigned int i = 0; i < Length; i++)
{
printf("%02X ", Buffer[i] & 0xFF);
}
printf("\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
DefaultPacket<MyAction1> Action(0xAA, 0xBB);
Action->MyData1 = 0xCCCCCCCC;
Action->MyData2 = 0xDDDD;
strcpy_s(Action->MyData3, 10, "Wolfulus");
SerializedBuffer MyBuffer;
Action.Serialize(MyBuffer);
// WolfEncoder::EncodeBuffer(MyBuffer.Buffer+2 /*dont encode length*/, MyBuffer.Size-2); // Game Hacking Issues -> Protect
cout << "Packet Size : " << Action.GetPacketSize() << endl;
cout << "Packet Protocol Type : " << Action.GetProtocolType() << endl;
cout << "Packet Protocol Action : " << Action.GetProtocolAction() << endl;
cout << endl;
DisplayHex((unsigned char*)MyBuffer.Buffer, MyBuffer.Size);
system("pause");
return 0;
}
Output:
Code:
Packet Size : 22
Packet Protocol Type : 170
Packet Protocol Action : 187
16 00 AA 00 BB 00 CC CC CC CC DD DD 57 6F 6C 66 75 6C 75 73 00 00
Press any key to continue . . .
Code:
Packet Size : 22 >> 2 len + 2 type + 2 id, + 4 mydata1, + 2 mydata2, +10 mydata3 = 22 ok.
Packet Protocol Type : 170 >> 0xAA ok.
Packet Protocol Action : 187 >> 0xBB ok.
h.Size ac.Type ac.Ind MyData1 MyData2 MyData3
[16 00] [AA 00] [BB 00] [CC CC CC CC] [DD DD] [57 6F 6C 66 75 6C 75 73 00 00]
---
can you guys tell me if i did it right? i mean, if it is a good implementation or if i'll have any issues with it... just by looking
Last edited by wolfulus; September 2nd, 2009 at 03:33 PM.
-
September 2nd, 2009, 09:45 PM
#10
Re: class size changes when inheriting abstract ones...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|