类的虚函数派生形式结构

时间:2012-05-10 19:15:36

标签: c++ segmentation-fault virtual

我有一个派生自C结构的类。除了构造函数中的初始化,析构函数期间的去初始化函数以及调用C函数的一些其他方法之外,该类没有做任何特殊操作。基本上,它是一个普通的包装器。使用GCC,它抱怨我的析构函数不是虚拟的,所以我就这样做了。现在我遇到了段错误。

/* C header file */
struct A
{
  /* ... */
}

// My C++ code
class B : public A
{
public:
  B() { /* ... init ... */ }
  virtual ~B() { /* ... deinit ... */ }

  void do()
  {
    someCFunction(static_cast<A *>(this));
  }
};

我始终假设static_cast将返回指向基类的正确指针,从而修剪虚拟表指针。所以情况可能并非如此,因为我在C函数中得到了段错误。

删除virtual关键字后,代码工作正常,但我收到gcc警告。对此最好的解决方法是什么?随意开导我:)。

3 个答案:

答案 0 :(得分:4)

A*的显式和隐式转换都是安全的。既不需要显式转换,也不会在任何地方引入vtable,或类似的东西。如果情况并非如此,那么该语言将根本无法使用。

  

我总是假设static_cast会返回   指向基类的正确指针,修剪掉虚拟表   指针。

绝对正确。

只有在virtual具有类型delete ptr;的情况下调用ptr - 或者手动调用析构函数时,析构函数才需要为A*。而A的析构函数必须是虚拟的,而不是虚构的。

无论代码中存在什么问题,它都与显示的代码无关。您需要大幅扩展样本。

答案 1 :(得分:1)

基类的析构函数应该是虚拟的。否则,您可能会遇到未定义的行为。这只是一个推测,因为代码不足以说明实际原因。

尝试将A的析构函数设为虚拟,然后查看它是否崩溃。

请注意,除了默认访问级别之外,classstruct是相同的事情,因此一个类和另一个结构与它无关。

编辑:如果A是C-struct,请使用合成而不是继承 - 即在A内部拥有B成员,而不是扩展它。没有必要推导出来,因为多态性是不可能的。

答案 2 :(得分:1)

这不是static_cast的工作方式。指向对象的指针仍然是相同的指针,只是具有不同的类型。在这种情况下,您将指向派生类型(B)的指针转换为指向基类型(A)的指针。

我的猜测是,转换指针实际上并没有改变指针值,即它仍然指向相同的内存地址,即使它被转换为A*指针类型。请记住,structclass是C ++中的同义词。

正如@Luchian所说,如果你正在混合C和C ++,最好将普通的旧C结构(及其指针)保持为普通的旧C结构,并使用类型组合而不是继承。否则,您将在窗口下混合使用不同的指针实现。无法保证C结构和C ++类的内部排列是相同的。

<强>更新

您应该使用extern "C"规范包围C struct声明,以便C ++编译器知道该struct是纯C结构:

extern "C"
{
    struct A
    {
        ...
    };
}

或者:

extern "C"
{
#include "c_header.h"
}