【问题标题】:Initialization of members when inheriting from extern C struct从外部 C 结构继承时初始化成员
【发布时间】:2015-06-27 01:09:46
【问题描述】:

Mixing C and C++ Code in the Same Program中给出了下面的例子(这里略略简写到相关部分)。假设 buf.h 包含以下内容:

struct buf {
    char* data;
    unsigned count;
};

// some declarations of existing C functions for handling buf...

那么建议使用

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

class mybuf : public buf {
public:
    mybuf() : data(0), count(0) { }

    // add new methods here (e.g. wrappers for existing C functions)...
};

为了在 C++ 中使用具有附加功能的结构。

但是,这显然会产生以下错误:

error: class `mybuf' does not have any field named `data'
error: class `mybuf' does not have any field named `count'

How can I initialize base class member variables in derived class constructor?C++: Initialization of inherited fieldInitialize parent's protected members with initialization list (C++) 中解释了这种情况的原因。

因此,我有以下两个问题:

  1. 提供的代码是完全错误还是我遗漏了一些相关方面? (毕竟,这篇文章似乎来自一个有信誉的来源)
  2. 达到预期效果的正确方法是什么(即将 C 结构转换为 C++ 类并添加一些便利方法,例如构造函数等)?

更新:按照建议使用聚合初始化,即

mybuf() : buf{0, 0} {}

有效,但需要 C++11。因此,我添加以下问题:

  1. 使用C++03,有没有比使用下面的构造函数更好的方法来达到预期的结果?

    mybuf() {
      data = 0;
      count = 0;
    }
    

【问题讨论】:

  • 看起来像一个复制和粘贴错误。在同一页的前面,作者实现了一个类mybuf,它具有datacount 成员。
  • 为什么要在结构周围放置一个外部“C”?没有必要。
  • @Cyber​​Spock 查看代码的原始来源,这是关于混合 C 和 C++ 代码并且头文件包含一些函数声明,我已经编辑了上面的代码以使其清楚。
  • @godfatherofpolka 无论是 C 还是 C++,结构都是结构。没有理由将其包装在 extern "C" 块中。您的问题不是关于混合 C-C++,而是关于在基类中初始化成员变量。
  • @Cyber​​Spock 是的,你是对的,extern "C" 与问题无关,但我将其保留在那里以提供问题的一些上下文,特别是强调结构是以纯 C 结构形式给出,因此不能在结构级别上进行初始化(如果它是 C++ 结构,这将是显而易见的答案)。

标签: c++ c inheritance struct init


【解决方案1】:

如果您可以使用与 c++11 兼容的编译器,那么这将是使用 aggregate initialization 的初始化列表的完美用例。

mybuf() : buf{0, 0}
{}

【讨论】:

  • 谢谢,这行得通!如果不能使用 C++11,正确的方法是什么?
【解决方案2】:

如果您的编译器支持 C++11,则一种“正确”的方法是使用例如

mybuf() : buf{0, 0} {}

【讨论】:

  • 谢谢,这行得通!如果不能使用 C++11,正确的方法是什么?
【解决方案3】:

这与混合 C 和 C++ 无关。您正在尝试初始化不存在的成员;它们存在于基类中是不够的。您需要初始化基础本身。

在这种情况下,使用聚合初始化:

class mybuf : public buf
{
public:
    mybuf() : buf{0, 0} {}
};

【讨论】:

  • 谢谢,这行得通!如果不能使用 C++11,正确的方法是什么?
  • 也许是 GCC 的扩展; buf({0,0})
【解决方案4】:
class mybuf : public buf {
public:
    mybuf();    
    // add new methods here (e.g. wrappers for existing C functions)...
};

const buf init = {0,0};

mybuf::mybuf() : buf(init) {};

会起作用的。

我在一些编译器上看到了这项工作,但没有方便的标准来检查它是标准的还是扩展的。

class mybuf : public buf {
public:
    mybuf() : buf(init) { }

    // add new methods here (e.g. wrappers for existing C functions)...

    private:

    const buf init = {0,0};
};

【讨论】:

  • 关于您的第二种方法:构造函数行上的 GCC 4.9 accepts it,CLang 3.6rc2 gives a -Wuninitialized warning,构造函数行上带有错误 409 的 ICC 13 rejects it,以及 MSVC 17 (VS2012 ) 以 C2059 'unexpected {' 错误后跟 C2334 'unexpected token(s) before '{'' 和 C2065 'undeclared identifier' 在构造函数定义中拒绝初始化程序。我会说它要么是 GCCism/GCC 扩展,要么是 UB。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多