C++ 我可以将基类提升为子类吗?
我有一个a级,如下所示:C++ 我可以将基类提升为子类吗?,c++,superclass,base-class,C++,Superclass,Base Class,我有一个a级,如下所示: 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
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)
{
}
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)
{
}
以及从a类衍生而来的B类,如下所示:
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)
{
}
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)
{
}
然后我接收一个大小为uSize的内存块lpData。uSize与MY_数据的大小相同。但我事先不知道我是谁
我的目的是确定内存块的类型,并调用相应的处理函数来处理类型后面的数据。
因此,我在下面的代码片段中这样做:
CClassA a(lpData, uSize);
if (a.m_Data.m_nType == 0)
{
CClassB& b = (CClassB&)a;
b.ProcessBData();
}
我将使用内存块创建一个类A的实例,然后如果数据的类型为0,那么我们将知道数据属于类B,然后我将把原始实例提升到它的子类ClassB,这样我们就可以调用ProcessBData来处理特定于类B的数据
然而,我怀疑这是否有效,因为类B是a的子类,所以它将包含比类a更多的条目,通过将基类复制到它的子类,这会导致问题吗
另一种解决方案是在知道类型为0后,使用相同的内存块创建类B的新实例。但是,这会降低性能,因为我们复制内存块两次,一次复制到类A,一次复制到类B
那么如何解决这样的难题呢
谢谢如果不添加/获取有关数据内容的任何类型的信息,就无法在运行时获取类型信息。如果您能够以某种方式获取类型信息,那么有一些解决方案
struct MY_DATA::m_nType
,通过查看数据获取其类型(可能数据中有某种标识符,特定类型的特定值范围,不同数据类型的不同大小)MY_DATA
的声明并使用std::cout << sizeof(unsigned int) << std::endl;
>> 4
std::cout << sizeof(bouble) << std::endl;
>> 8
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;
}
如果你真的只是得到一堆内存,而没有任何关于它的内容的进一步信息,并且想要得到信息的类型=>那么你的设计就无法修复了。弄清楚你到底想做什么是一种挑战。。。据我所知,如果您试图从基类强制转换到派生类,这可能是格式错误的,并可能导致U.B.或不受欢迎的定义行为。。。这真的很难说,因为这取决于它将被用于的上下文,角落案例等等 这里有一个可能的建议结构可以帮助你。。。它通过模板专门化和CRTP结构的组合使用多态继承。它可能看起来像这样:
template<class T, int type>
class Data {
protected:
Data() {};
public:
virtual ~Data() {}
};
template<class T>
class Data<T, 0> {
protected:
DWORD data;
};
template<class T>
class Data<T, 1> {
protected:
double data;
};
template<typename T, int type>
class Base : public Data<T, type> {
protected:
Base() {}
public:
virtual ~Base() {}
virtual void processData() {}
};
class ClassA : public Base<ClassA, 0> {
public:
ClassA(const BYTE* lpData, UINT size) {
::memcpy( &(this->data), lpData, size);
}
void processData() override {
return;
}
};
class ClassB : public Base<ClassB, 1> {
public:
ClassB(const BYTE* lpData, UINT size) {
::memcpy( &(this->data), lpData, size);
}
void processData() override {
data++;
}
};
模板
类数据{
受保护的:
数据(){};
公众:
虚拟~Data(){}
};
模板
类数据{
受保护的:
DWORD数据;
};
模板
类数据{
受保护的:
双重数据;
};
模板
类库:公共数据{
受保护的:
Base(){}
公众:
虚拟~Base(){}
虚拟void processData(){}
};
A类:公共基地{
公众:
ClassA(常量字节*lpData,单位大小){
::memcpy(&(this->data),lpData,size);
}
void processData()重写{
返回;
}
};
B类:公共基地{
公众:
ClassB(常量字节*lpData,单位大小){
::memcpy(&(this->data),lpData,size);
}
void processData()重写{
数据++;
}
};
如果基类实际上不是子类,则绝对不要将其强制转换为子类。在我看来,实例化哪个类的决定应该由工厂函数根据手头的数据来处理。为什么不简单地实现一些移动语义呢?或者,如果旧对象必须保持有序,那么让另一个类不是子类,而是存储指向第一个类的指针。我也确实认为指针是正确的方法。工厂创建一个包含指针的对象怎么样?您的代码段包含UdeVior。在某些情况下,它可能与某些编译器一起工作,但在其他情况下它会失败。如果ClassB
会有额外的数据成员,那肯定是非常危险的。从“写一个完美的问题”>开始,许多海报陷入的一个陷阱是问如何实现一些“小”目标,但永远不要说更大的目标是什么。
那么你的目标是什么?什么是lpData
和uSize
,您如何使用它们?如何初始化m_数据?在这种情况下,为什么需要继承?如果没有这些信息,就不会出现两难的局面,因为不清楚选项是什么。实际上,我在评论中使用了指针建议。无论如何,谢谢你。
template<class T, int type>
class Data {
protected:
Data() {};
public:
virtual ~Data() {}
};
template<class T>
class Data<T, 0> {
protected:
DWORD data;
};
template<class T>
class Data<T, 1> {
protected:
double data;
};
template<typename T, int type>
class Base : public Data<T, type> {
protected:
Base() {}
public:
virtual ~Base() {}
virtual void processData() {}
};
class ClassA : public Base<ClassA, 0> {
public:
ClassA(const BYTE* lpData, UINT size) {
::memcpy( &(this->data), lpData, size);
}
void processData() override {
return;
}
};
class ClassB : public Base<ClassB, 1> {
public:
ClassB(const BYTE* lpData, UINT size) {
::memcpy( &(this->data), lpData, size);
}
void processData() override {
data++;
}
};