Почему компилятор не жалуется в определении конструктора производного класса?

#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.