2015-09-13 5 views
-1

У меня есть предупреждение от GCC о том, что базовый класс должен быть инициализирован в конструкторе копирования. Проблема в том, что I полагает, что первоначальное намерение является его конструктором, но не конструктором копии. Вот то, что упрощенная версия выглядит (я добавил инициализатору Base() в ответ на предупреждение):Как сообщить компилятору, что конструктор не является конструктором копирования?

class Base { ... }; 

class Derived : public Base 
{ 
    public: 
    Derived(Derived& d, int x = 0) 
     : Base(), m_b(d) { ... }; 
    protected: 
    Base& m_b; 
}; 

class Derived обеспечивает интерфейс Base, и он имеет Base член. Конструкция такова, что данные могут перетекать из источника в приемник, причем промежуточные промежуточные объекты могут преобразовывать или обрабатывать данные (произвольные, но ограниченные интерфейсом).

Важное значение имеет различие между конструктором и конструктором копии. В случае конструктора Base инициализируется по умолчанию; и в случае конструктора копирования Base инициализируется rhs.

Достаточно ли использовать базу default constructedBase, чтобы дать компилятору намек на то, что его конструктор, но не конструктор копирования?

Если нет, то как сообщить компилятору, что конструктор не конструктор копирования? Я рад использовать расширение GCC, например, __attribute__, чтобы направлять компилятор в правильном направлении.

(Другой вариант, изменить подпись, не может произойти в настоящий момент, поскольку он нарушает требования к версированию на большинстве основных платформ, например Apple).


Вот файлы в вопрос:

Здесь предупреждает компилятор (пространство имен было удалено для краткости):

g++ -DDEBUG -g2 -O2 -Wall -Wextra -fPIC -march=native -pipe -c asn.cpp 
asn.cpp: In copy constructor ‘DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder&, byte)’: 
asn.cpp:497:1: warning: base class ‘class ByteQueue’ should be explicitly initialized in the copy constructor [-Wextra] 
DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) 

asn.cpp:497 указывает на line 487 (второй конструктор) в немодифицированных онлайн-источниках.

Система Fedora 22, x86_64, полностью исправлен, с GCC 5.1.1:

$ uname -a 
Linux localhost.localdomain 4.1.6-201.fc22.x86_64 #1 SMP Fri Sep 4 17:49:24 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux 
$ lsb_module 
bash: lsb_module: command not found... 
$ g++ --version 
g++ (GCC) 5.1.1 20150618 (Red Hat 5.1.1-4) 
... 
+0

Я не получаю это предупреждение с или без 'Base()' с GCC 5.2. – chris

+5

Конструктор, который вы показываете, не является конструктором копирования. Предупреждение о чем-то другом. Покажите полную программу, которая воспроизводит проблему, вместе с точным и полным сообщением об ошибке. –

+2

Я не получаю никаких предупреждений с вашим кодом. Какой компилятор/флаги вы используете? – Galik

ответ

3

В вашем реальном коде, конструктор в вопросе является конструктор копирования, потому что вызываемая с одним аргументом типа класса (поскольку второй параметр имеет аргумент по умолчанию). Обратите внимание, что компилятор даже не создает конструктор копии по умолчанию, поскольку вы предоставляете свой собственный конструктор копирования.

Итак, чтобы предупредить вас, просто инициализируйте базовый класс явно; компилятор вправе рассматривать его как конструктор копирования, и вам также следует.

+0

Спасибо Agnew. Лучшее, что я могу сказать (я не писал код), намерение исходного кода - это конструктор, а не конструктор копирования. Каков наилучший способ приступить к переходу к первоначальным намерениям? Если вы можете помочь с этим, я был бы рад принять ответ. – jww

+0

@jww Если код работает нормально как есть, просто добавьте базовую инициализацию, чтобы избавиться от предупреждения. Если вы хотите активно * предотвратить *, что ctor от копирования ctor, вам придется удалить аргумент по умолчанию. По определению, ctor класса 'X', вызываемый одним аргументом типа' X', является копией ctor. – Angew

+0

Да, это ставит код в плохом месте из-за требований к версированию. Я не думаю, что подпись может измениться, не выполняя серьезную ошибку. Отсюда причина, по которой я пытался обойти это, сообщив компилятору о том, что должно происходить. Возможно, используя GCC '__attribute__' или подобное ... – jww

0

Каков наилучший способ рассказать компилятору о его конструкторе, а не о конструкторе копирования?

Поскольку является копия конструктора, у вас есть два варианта:

  1. Hack исходный код компилятора таким образом, что он извращает ваши;
  2. Станьте членом основной рабочей группы и каким-то образом сделайте так, чтобы это было , а не конструктор копирования в некоторой будущей версии стандарта C++.
+2

Мне нравится этот ответ. :) –

+1

Только на переполнение стека можно на 100% фактический и прямой ответ атаковать бригада нижестоящих! –

+0

Я * обожаю * иронию в критике меня в 22K, когда это то, что вы предлагаете в 171K и предметной экспертизе. Это точно так же, как вы сказали: * «Конечно, всегда было странное исключение (например, вы!)» *. О, ирония .... – jww

Смежные вопросы