Подтвердить что ты не робот

Инициализация членов при наследовании от extern C struct

В Смешивание кода C и С++ в той же программе приводится следующий пример (немного сокращенный здесь для соответствующих частей). Предположим, что 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)...
};

чтобы использовать структуру внутри С++ с добавленными функциями.

Однако это явно приведет к следующей ошибке:

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

Причины этого объясняются в Как инициализировать переменные-члены базового класса в конструкторе производного класса?, С++: Инициализация наследуемого поля и Инициализировать защищенные члены родителя с помощью списка инициализации (С++).

Таким образом, у меня есть следующие два вопроса:

  • Является ли приведенный код просто неправильным или я не хватает какого-либо релевантного аспекта? (В конце концов, статья, похоже, основана на авторитетном источнике)
  • Каков правильный способ достижения желаемого эффекта (т.е. превращение C-структуры в класс С++ и добавление некоторых удобных методов, таких как, например, конструктор и т.д.)?

Обновление: использование инициализации агрегации, как предлагается, т.е.

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

работает, но требует С++ 11. Поэтому я добавляю следующий вопрос:

  1. Используя С++ 03, есть ли лучший способ достичь желаемого результата, чем использовать следующий конструктор?

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

Ответ 1

Если вы можете использовать компилятор С++ 11, то это будет идеальным вариантом для списка инициализаторов, используя агрегатную инициализацию.

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

Ответ 2

Один "правильный" способ, если ваш компилятор совместим с С++ 11, должен использовать, например,

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

Ответ 3

Это не имеет никакого отношения к смешиванию C и С++. Вы пытаетесь инициализировать членов, которых не существует; что они существуют в базовом классе, недостаточно. Вам нужно инициализировать базу.

В этом случае используйте агрегатную инициализацию:

class mybuf : public buf
{
public:
    mybuf() : 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};
};