Класс “предупреждения компилятора GNU имеет виртуальные функции, но невиртуальный деструктор”

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

58
задан LogicStuff 22 December 2015 в 12:56
поделиться

7 ответов

Это - более или менее ошибка в компиляторе. Обратите внимание, что в более свежих версиях компилятора это предупреждение не становится брошенным (по крайней мере, в 4,3, это не делает). Наличие деструктора быть защищенным и невиртуальное, абсолютно законно в Вашем случае.

См. здесь для превосходной статьи Herb Sutter на предмете. От статьи:

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

65
ответ дан Greg Rogers 24 November 2019 в 19:03
поделиться

Некоторые комментарии к этому ответу касаются более раннего ответа, который я дал, который был неправильным.

А защитил средства деструктора, которыми это можно только назвать от базового класса, не через удаляют. Это означает, что ITest* не может быть непосредственно удален, только производный класс может. Производный класс может хотеть виртуальный деструктор. Нет ничего неправильно с Вашим кодом вообще.

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

9
ответ дан Airsource Ltd 24 November 2019 в 19:03
поделиться

Если Вы настаиваете на том, чтобы делать это, разрешение и передаете -Wno-non-virtual-dtor GCC. Это предупреждение, кажется, не включено по умолчанию, таким образом, Вы, должно быть, включили его с -Wall или -Weffc++. Однако я думаю, что это - полезное предупреждение, потому что в большинстве ситуаций это было бы ошибкой.

4
ответ дан bk1e 24 November 2019 в 19:03
поделиться

Это - интерфейсный класс, таким образом, разумно, что Вы не должны удалять объекты, реализовывая тот интерфейс через тот интерфейс. Общий падеж этого является интерфейсом для объектов, созданных фабрикой, которая должна быть возвращена к фабрике. (Имеющие объекты содержат указатель на свою фабрику, могло бы быть довольно дорогим).

я согласился бы с наблюдением, что GCC жалуется. Вместо этого это должно просто предупредить при удалении ITest*. Это - то, где реальная опасность находится.

2
ответ дан MSalters 24 November 2019 в 19:03
поделиться

Мое персональное представление состоит в том, что Вы были бы, делая корректную вещь, и компилятор повреждается. Я отключил бы предупреждение (локально в файле, который определяет интерфейс), если это возможно,

я нахожу, что использую этот шаблон (маленький 'p') довольно много. На самом деле я нахожу, что моим интерфейсам более свойственно защитить dtors, чем это для них для имения общедоступных. Однако я не думаю, что это на самом деле настолько распространено идиома (это не становится говорившим о так очень), и я предполагаю назад, когда предупреждение было добавлено к GCC, было уместно попытаться осуществить более старое 'dtor, должно быть виртуальным, если у Вас есть виртуальные функции' правило. Лично я обновил то правило к 'dtor, должно быть виртуальным, если Вы имеете виртуальные функции и хотите, чтобы пользователи были в состоянии еще удалить экземпляры интерфейса через интерфейс, dtor должен быть защищен и не виртуальный' давным-давно;)

2
ответ дан Len Holgate 24 November 2019 в 19:03
поделиться

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

0
ответ дан INS 24 November 2019 в 19:03
поделиться

Если бы у Вас был код в одном из ITest методы, которые попробовали к delete самом (плохая идея, но законный), деструктор производного класса не назвали бы. Необходимо все еще сделать деструктор виртуальным, даже если Вы никогда не намереваетесь удалить полученный экземпляр через указатель базового класса.

0
ответ дан Adam Rosenfield 24 November 2019 в 19:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: