void foo() {
int i = 0;
...
if(something) {
int i = 0;
...
}
}
Объявление члена с тем же именем в производном классе потенциально может привести к ошибкам. Но, во-первых, это не обязательно будет так. И, во-вторых, можно увидеть случаии, когда вы вообще не можете на это повлиять.
Например #1. Вы пользуетесь чужим классом Base, в котором Base::i не было. Вы сделали Derived::i. Прошло какое-то время и Base доработали, добавив туда Base::i. Захотите ли вы менять свой Derived?
Например #2. Шаблоны и наследование.
class Base {
protected:
int i_;
...
};
class Derived : public Base {
...
};
class Mixin {
protected:
int i_;
...
};
template<typename M>
class MegaDerived : public Derived, public M {
...
};
...
MegaDerived<Mixin> d; // oops!
Но, во-первых, это не обязательно будет так. И, во-вторых, можно увидеть случаии, когда вы вообще не можете на это повлиять.
Из разряда «мне не надо, значит никому не надо». Возможны случаи, в которых такое предупреждение может помочь. Это уже достаточный повод добавить его, хотя бы в каком-то своём внутреннем инструменте.
Вот в Clang, например, есть такое предупреждение, но оно не включается ни в -Wall, ни даже в -Wextra. Позреваю, что примерно по тем же соображениям — большое количество ложных срабатываний.
Это не ошибка
Кстати, по ссылке на SO, приведённой ТСом, просят предупреждение, а не сообщение об ошибке. Все в курсе, что это не является ошибкой.
Возможны случаи, в которых такое предупреждение может помочь.
Я до сих пор нахожусь в недоумении от того, где в подобных сценариях ТС видит ошибку (хоть «семантическую», хоть «программирования»). Собственно, отсюда и появились мои комментарии.
То, что пересечение имен может быть чревато, так это очевидно.
Было бы здорово, если бы часть проверок можно было автоматизировать. Понятное дело, что нельзя полностью заменить человека на ревью. Но если дать ему больше инструментов, станет лучше. Ведь так?
Раз уже потестили код gcc и сlang, решил для полноты картины проверить код имеющимися под руками анализаторами и компиляторами:
Потестил код MSVC2017 и PVS Studio и cppcheck
PVS Studio выдаёт:
V703 It is odd that the 'i' field in derived class 'Child' overwrites field in base class 'Mother'. Check lines: main.cpp:19, main.cpp:10. main.cpp 19
MSVC 2017 не выдаёт предупреждений насчёт этого (хотя просто предупреждения об обычном затенении выдаются)
Cppcheck выдаёт:
Id: duplInheritedMember
Summary: The class 'Child' defines member variable with name 'i' also defined in its parent class 'Mother'.
Message: The class 'Child' defines member variable with name 'i' also defined in its parent class 'Mother'.
То, что пересечение имен может быть чревато, так это очевидно.
Лол :-) Чего тут удивляться? :-) В мире программирования полным полно шлангов, которые любят нарываться на неприятности :-) Особенно, это касается цепепе :-) Так, есть любители делать в классах члены данных без префиксов и суффиксов, либо определять члены данных открытыми, либо определять функции доступа к данным через макросы или ещё какую-нибудь задницу :-) Уж где где, а в цепепе таких возможностей масса :-) Печально только тем, у кого отношение к коду не как к параше, а как к произведению :-) Остальным плевать, даже когда их компилятор заваливает всевозможными варнингами :-) Но самое удивительное, что такого закрытого кода, который ещё и работает и приносит прибыль великое множество :-) А вот это уже не так очевидно и вообще является феноменом :-)
Дык, я согласен с тем, что иметь подобное опциональное сообщение было бы полезно. Но вот по поводу того, что это «семантическая ошибка» я до сих пор недоумеваю.
Тем более, что вот такой прием:
struct default_policy {
using mutex_type = std::mutex;
...
};
struct my_custom_policy : public default_policy {
using mutex_type = some_custom_nonportable_mutex;
};
используется широко и базируется на той же самой возможности. Но проблем, как правило, не вызывает.
Изврат. В джавке живут же как-то без макросов и дефайнов и ничего. Тут дело не крестах. Это всё из-за тяжёлого детства, проведённого вместе с компилятором сишечки.