gpt4 book ai didi

c++ - 在 C : Derived to base conversions 中包装 C++

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:16:42 26 4
gpt4 key购买 nike

我正在将一个简单的 C++ 继承层次结构包装到“面向对象的”C 中。我试图弄清楚在将指向 C++ 对象的指针视为指向不透明 C 结构的指针时是否存在任何问题。特别是在什么情况下派生到基的转换会出现问题?

类本身比较复杂,但层级较浅,仅采用单继承:

// A base class with lots of important shared functionality
class Base {
public:
virtual void someOperation();
// More operations...

private:
// Data...
};

// One of several derived classes
class FirstDerived: public Base {
public:
virtual void someOperation();
// More operations...

private:
// More data...
};

// More derived classes of Base..

我计划通过以下相当标准的面向对象的 C 将其公开给 C 客户端:

// An opaque pointers to the types
typedef struct base_t base_t;
typedef struct first_derived_t first_derived_t;

void base_some_operation(base_t* object) {
Base* base = (Base*) object;
base->someOperation();
}

first_derived_t* first_derived_create() {
return (first_derived_t*) new FirstDerived();
}

void first_derived_destroy(first_derived_t* object) {
FirstDerived* firstDerived = (FirstDerived*) object;
delete firstDerived;
}

C 客户端只传递指向底层 C++ 对象的指针,并且只能通过函数调用来操作它们。所以客户最终可以做类似的事情:

first_derived_t* object = first_derived_create();
base_some_operation((base_t*) object); // Note the derived-to-base cast here
...

并让对 FirstDerived::someOperation() 的虚拟调用按预期成功。

这些类不是 standard-layout但不要使用多重或虚拟继承。这保证有效吗?

请注意,如果重要的话,我可以控制所有代码(C++ 和 C 包装器)。

最佳答案

// An opaque pointers to the types
typedef struct base_t base_t;
typedef struct first_derived_t first_derived_t;

// **********************//
// inside C++ stub only. //
// **********************//

// Ensures you always cast to Base* first, then to void*,
// then to stub type pointer. This enforces that you'll
// get consistent a address in presence of inheritance.
template<typename T>
T * get_stub_pointer ( Base * object )
{
return reinterpret_cast<T*>(static_cast<void*>(object));
}

// Recover (intermediate) Base* pointer from stub type.
Base * get_base_pointer ( void * object )
{
return reinterpret_cast<Base*>(object);
}

// Get derived type pointer validating that it's actually
// the right type. Returs null pointer if the type is
// invalid. This ensures you can detect invalid use of
// the stub functions.
template<typename T>
T * get_derived_pointer ( void * object )
{
return dynamic_cast<T*>(get_base_pointer(object));
}

// ***********************************//
// public C exports (stub interface). //
// ***********************************//

void base_some_operation(base_t* object)
{
Base* base = get_base_pointer(object);
base->someOperation();
}

first_derived_t* first_derived_create()
{
return get_stub_pointer<first_derived_t>(new FirstDerived());
}

void first_derived_destroy(first_derived_t* object)
{
FirstDerived * derived = get_derived_pointer<FirstDerived>(object);
assert(derived != 0);

delete firstDerived;
}

这意味着您始终可以执行如下所示的转换。

first_derived_t* object = first_derived_create();
base_some_operation((base_t*) object);

这是安全的,因为 base_t*指针将被转换为 void* , 然后到 Base* .这比之前发生的事情少了一步。注意顺序:

  1. FirstDerived*
  2. Base* (通过隐式 static_cast<Base*> )
  3. void* (通过 static_cast<void*> )
  4. first_derived_t* (通过 reinterpret_cast<first_derived_t*> )
  5. base_t* (通过 (base_t*) ,这是 C++ 风格的 reinterpret_cast<base_t*> )
  6. void* (通过隐式 static_cast<void*> )
  7. Base* (通过 reinterpret_cast<Base*> )

对于包装 FirstDerived 的调用方法,你会得到一个额外的类型转换:

  1. FirstDerived* (通过 dynamic_cast<FirstDerived*> )

关于c++ - 在 C : Derived to base conversions 中包装 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9168521/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com