微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c++11 通过指针访问联合内容的成员

如何解决c++11 通过指针访问联合内容的成员

正在为向 ESP8266 设备发送信息的特定硬件实现串行接收库,我遇到了以下问题

一些背景:

  • 我使用 sloeber eclipse IDE 进行 arduino 编程,使用 Arduino IDE 也存在同样的问题
  • __cplusplus 给了我 201103,所以我假设我使用的是 c++11

设置说明:

  • 我有派生类代表从串行接收的解释包
  • 这些类都是基类的派生形式,基类实现了一些常用方法,这里是methodA(实际上:长度为 数据,以及数据的吸气剂)
  • 为了转发这些数据包,我创建了一个类,其中包含一个结构体 (sData) 的成员,该结构体内部有一个标记联合。为简单起见,我在这里只使用 sData 而不是包含它的类。
  • union uUnion 是以派生包的形式保存数据包内容的联合,一次只有一个,但能够包含每个可用的派生类。
  • 我不使用任何动态对象创建(没有新的),以防止内存泄漏

也许这个问题有更好的解决方案。想法表示赞赏。但我想重点讨论为什么我的实现不起作用

问题

联合外派生类的成员函数的使用。 我可以毫无问题地直接打电话给他们。 但是我无法从联合中创建指向派生类实例的指针并调用该成员。

//this is the base class
class cBaseA{
public:
    virtual void methodA(void){
            Serial.print(" A ");
            Serial.println(i);
        }
    int i; //some attribute to work with
private:
};
//first derived class
class cDerivedA: public cBaseA{
public:
     void methodA(void) {
        Serial.print(" DerivedA ");
        Serial.print(i);
        Serial.print(" ");
        Serial.println(ii);
    }
     int ii; //additional attribute
private:
};
//second derived class
class cDerivedB: public cBaseA{
public:

     void methodA(void) {
        Serial.print(" DerivedB ");
        Serial.print(i);
        Serial.print(" ");
        Serial.println(ii);
    }
    int ii;
private:
};
//third derived class
class cDerivedC: public cBaseA{
public:
     void methodA(void) {
            Serial.print(" DerivedC");
            Serial.print(i);
            Serial.print(" ");
            Serial.println(ii);
        }
     int ii;
private:
};
//this is the structure to pass different derived instances around
struct sData{
    enum eDataType{
        eunkown,eDerivedA,eDerivedB,eDerivedC
    } DataType;
    union uUnion{
        cDerivedA DerivedA;
        cDerivedB DerivedB;
        cDerivedC DerivedC;
        ~uUnion(){};
        uUnion(){};
    } ;
    uUnion DataUnion;
    sData(void){DataType=eDataType::eunkown;};
    sData(const sData &Data){
        this->DataType=Data.DataType;
        switch(this->DataType){
            case eDataType::eDerivedA:
                this->DataUnion.DerivedA=Data.DataUnion.DerivedA;break;
            case eDataType::eDerivedB:
                this->DataUnion.DerivedB=Data.DataUnion.DerivedB;break;
            case eDataType::eDerivedC:
                this->DataUnion.DerivedC=Data.DataUnion.DerivedC;break;
            case eDataType::eunkown:
                break;
        }
    }
    ~sData(){};
};


void DataFunction(struct sData *Data){
    Serial.println("A1:");
    Data->DataUnion.DerivedB.methodA();   //works fine

    cDerivedB *DerivedB;
    DerivedB=&(Data->DataUnion.DerivedB); //this works
    DerivedB->methodA();                  //compiles,but execution exception,code 28

}

void setup(){
    Serial.begin(9600);
    delay(2000);
sData Data;
    cDerivedB DerivedB1;
    DerivedB1.i=1;
    DerivedB1.ii=2;
    Data.DataType=sData::eDataType::eDerivedB;
    Data.DataUnion.DerivedB=DerivedB1;
    DataFunction(&Data);

}

到目前为止我尝试过的:

  • 没有 cBaseA 的虚拟析构函数没有影响(我已经尝试过)

  • 使工会匿名并没有改变任何东西

  • 引用联合内容会导致同样的错误

    cDerivedB &DerivedB; DerivedB=&(Data->DataUnion.DerivedB); DerivedB.methodA();

  • 我能够复制到基类的联合之外,但这会导致切片,并且调用在基类中结束,而不是我在派生类中需要的

问题是:如果可以直接调用,为什么会出现这个异常?

获取联合内容的句柄(指针、引用)并调用成员的正确方法是什么?我知道那里有讨论,联合应该只包含简单的数据类型。这只是编译器(c + 11)让我写这个的缺陷吗? 但是,直接访问仍然是可能的。为什么不通过指针?

如果有人能够把那朵云移开,我看不透,非常感谢。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。