I have a class A, as below:
struct MY_DATA
{
int m_nType;
union
{
DWORD m_dwBData;
double m_dCData;
} u;
};
class CClassA
{
public:
CClassA(BYTE* lpData, UINT uSize);
virtual ~CClassA(void);
MY_DATA m_Data;
};
CClassA::CClassA(BYTE* lpData, UINT uSize)
{
::memcpy(&m_Data, lpData, uSize);
}
CClassA::~CClassA(void)
{
}
and a class B derived from class A, as below:
class CClassB : public CClassA
{
public:
CClassB(BYTE* lpData, UINT uSize);
virtual ~CClassB(void);
void ProcessBData()
{
m_Data.u.m_dwBData ++;
}
};
CClassB::CClassB(BYTE* lpData, UINT uSize)
: CClassA(lpData, uSize)
{
}
CClassB::~CClassB(void)
{
}
Then I recieve a memory block lpData with size of uSize. uSize is same as the size of MY_DATA. But I don't know m_nType in advance.
My purpose is to determine the type of the memory block and invoke the corresponding processing function to process the data follows the type.
So I do that in the following code snippet:
CClassA a(lpData, uSize);
if (a.m_Data.m_nType == 0)
{
CClassB& b = (CClassB&)a;
b.ProcessBData();
}
I will create an instance of Class A by using a memory block, then if the type of the data is 0, then we will know the data is of class B, then I will promote the oriignal instance to its child class ClassB so that we can invoke ProcessBData to process the data specific to class B.
However, I doubt if this will work, since class B is a child class of A, so it will contain more entries than class A, by prmoting a base class to its child class, will that cause problem?
Another solution is create a new instance of Class B after knowing the type is 0, with the same memory block. However, this will decrease the performance, since we copy the memory block twice, once to class A and once to class B.
So how to solve such a delimma?
Thanks
You cannot get the type information at runtime, without adding/getting any type of information about the content of the data. There are some solutions if you can get type information somehow
struct MY_DATA::m_nType
befor processing it by getting it's type by looking at the data (maybe you have some kind of identifier inside your data, specific value ranges for a specific type, different size for different data types).MY_DATA
and use Runtime Type informationSolution 1: In case of DWORD and double you could for example use the size of the data
std::cout << sizeof(unsigned int) << std::endl;
>> 4
std::cout << sizeof(bouble) << std::endl;
>> 8
if you have acces to the original creation of data.
Solution 2: Well, apparently look at your documentation or ask the developer who provided the data.
Solution 3:
Use Runtime Type information for your MY_DATA
struct. This could look as following:
myclass.h
#pragma once
#include <cstdint>
struct MY_DATA{
virtual ~MY_DATA() {};
};
struct MY_DATA_B : public MY_DATA{
unsigned int data;
};
struct MY_DATA_C : public MY_DATA{
double data;
};
class CClassB {
public:
CClassB(MY_DATA* lpData);
virtual ~CClassB(void);
void myMethodB();
private:
MY_DATA_B* m_Data;
};
class CClassC {
public:
CClassC(MY_DATA* lpData);
virtual ~CClassC(void);
void myMethodC();
private:
MY_DATA_C* m_Data;
};
myclass.cpp
#include "myclass.h"
#include <cstring>
#include <iostream>
CClassB::CClassB(MY_DATA* lpData){
m_Data = new MY_DATA_B;
memcpy(m_Data, lpData, sizeof(MY_DATA_B));
}
CClassB::~CClassB(){
delete m_Data;
}
void CClassB::myMethodB(){
std::cout << "MY_DATA_B data: " << m_Data->data << std::endl;
}
CClassC::CClassC(MY_DATA* lpData){
m_Data = new MY_DATA_C;
memcpy(m_Data, lpData, sizeof(MY_DATA_C));
}
CClassC::~CClassC(){
delete m_Data;
}
void CClassC::myMethodC(){
std::cout << "MY_DATA_C data: " << m_Data->data << std::endl;
}
main.cpp
#include "myclass.h"
#include <iostream>
#include <typeinfo>
void execute(MY_DATA * ptr){
if(typeid(*ptr) == typeid(MY_DATA_B)){
CClassB a(ptr);
a.myMethodB();
}else if(typeid(*ptr) == typeid(MY_DATA_C)){
CClassC a(ptr);
a.myMethodC();
}
}
int main(){
MY_DATA_B b;
b.data = 5;
MY_DATA_C c;
c.data = 3.1;
MY_DATA * ptr = &b;
MY_DATA * ptr2 = &c;
execute(ptr);
execute(ptr2);
return 0;
}
This will result in the following output:
MY_DATA_B data: 5
MY_DATA_C data: 3.1
If you really just get a bunch of memory without any further information about it's content and want to get the type of the information => Then your design is broken beyond repair.