#c #visual-studio-2008
#c #visual-studio-2008
Вопрос:
Обратите внимание, что Derived
конструктор класса имеет ii
в качестве своего первого аргумента, но аргумент, переданный в Base
, был специально сделан равным i
.
class Base
{
protected:
int i;
public:
Base(int i) : i(i) {}
};
class Derived : public Base
{
private:
int k;
public:
Derived(int ii, int k) : Base(i), k(k) {} // Why not C2065: 'i' undeclared identifier
};
int main()
{
}
Комментарии:
1. Конечно, у компилятора здесь достаточно информации, чтобы знать, что код использует неинициализированную переменную. Он не жалуется, потому что команда разработчиков решила использовать свои драгоценные человеко-часы для разработки других вещей вместо этого (например, некоторой поддержки C 11 в VS2010).
Ответ №1:
Потому что i
это переменная-член, унаследованная от Base
, поэтому она определена. Вы можете свободно обращаться к переменным-членам в списках инициализатора, но то, что вы делаете, — это доступ к переменной до ее инициализации, что, я полагаю, является неопределенным поведением.
Комментарии:
1. Не могли бы вы привести пример, где это было бы допустимо?
2. @jaayrosa где то, что было бы допустимым? Инициализация базового элемента? В таком случае, если у
Base
вас нет конструктора для инициализацииi
, вы бы захотели инициализировать его самостоятельно, выполнивDerived(int ii, int k) : i(ii), k(k) {}
. Однако передача неинициализированной переменной в качестве аргумента никогда не является допустимой.3. Ваш пример для меня довольно ясен. Чего я не понимаю, так это почему компилятор не выдает C2065, поскольку переменная, переданная в
Base
, отличается от переменной, переданной вDerived
.4. @jaayrosa C2065 является
undeclared identifier
. Тем не менее,i
полностью, совершенно и безупречно объявлен, поэтому он не является необъявленным, поэтому он не будет выдавать C2065. Компилятору все равно, как вы используете аргументы, или даже используете ли вы их вообще.5. Итак, вы хотите сказать, что это определение
Derived
ctor было бы допустимым и все работало бы нормально :Derived(int ii, int k) : Base(ii), k(i) {}
Ответ №2:
Потому что он видит i
из базового класса и использует его в инициализаторе. Если вы измените protected на private, вы получите сообщение об Base::i
том, что оно является private.