来自c-Structure的安全dynamic_cast?

时间:2017-11-17 13:32:18

标签: c++ polymorphism

我有一些C结构通过一些将c ++部分链接在一起的算法来使用。

在输入端有一个c ++结构,它继承自c结构以添加一些成员。在输出端,有一些组件也可能需要这些数据。

有没有一种安全的方法来检测这个C结构实际上是否是提到的c ++类?也许通过使c ++子类具有多态性并使用动态强制转换?

struct Cstruct{
  int someData;
};


class CPPclass: public Cstruct{
  CPPclass(){};
  int someMoreData;
};

所以也许像是

class CPPclass: public Cstruct{
  virtual ~CPPclass(){};
  CPPclass(){};
  int someMoreData;
};

void test(Cstruct* i_c){
  auto cpp = dynamic_cast<CPPclass*>(i_c);   // < does not work, because Cstruct is not polymorphic
  if(cpp){
      // da;
  }
}

但也许?:

class CPPclassHelper: public Cstruct{
  virtual ~CPPclassHelper(){};
  CPPclassHelper(){};
  int someMoreData;
};

class CPPclass: public CPPclassHelper{
  virtual ~CPPclassHelper(){};
};

void test(Cstruct* i_c){
  auto cpph = static_cast<CPPclassHelper*>(i_c); 
  auto cpp = dynamic_cast<CPPclass*>(cpph );   
  if(cpp){
      // da;
  }
}

1 个答案:

答案 0 :(得分:1)

您可以自己维护类型信息。使用Cstruct的基础CPPclass的所有指针的静态集合。在CPPclass的所有构造函数中插入基数并在析构函数中删除。然后可以使用对该集合的查找来实现安全强制转换。

以下是一个例子:

struct CPPclass: Cstruct{
    CPPclass(){
        bases.insert(this);
    };
    CPPclass(const CPPclass&){
        bases.insert(this);
    };
    CPPclass(CPPclass&&){
        bases.insert(this);
    };
    ~CPPclass(){
        bases.erase(this);
    };

    static CPPclass* safe_cast(Cstruct* c) {
        auto it = bases.find(c);
        return it == bases.end()
            ? nullptr
            : static_cast<CPPclass*>(*it);
    }

private:
    static std::unordered_set<Cstruct*> bases;
};

用法:

int main() {
    CPPclass cpp;
    Cstruct  c;

    Cstruct* ptr_cpp = &cpp;
    Cstruct* ptr_c   = &c;

    std::cout << CPPclass::safe_cast(ptr_cpp) << '\n'; // some address equal to &cpp
    std::cout << CPPclass::safe_cast(ptr_c)   << '\n'; // null
}