Помогите с этими предупреждениями. [Удел] - PullRequest
5 голосов
/ 02 мая 2010

У меня есть набор кода, который имитирует базовую систему каталогизации библиотеки. Существует базовый класс с именем items, в котором определены общие переменные id, title и year и 3 других производных класса (DVD, Book и CD).

База [Предметы]

Производные [DVD, книга, CD].

Программы запускаются, однако я получаю следующие предупреждения, я не уверен, как их исправить.

>"C:\Program Files\gcc\bin/g++"  -Os -mconsole -g -Wall -Wshadow -fno-common mainA4.cpp -o mainA4.exe
In file included from mainA4.cpp:5:
a4.h: In constructor `DVD::DVD(int, std::string, int, std::string)':
a4.h:28: warning: `DVD::director' will be initialized after
a4.h:32: warning:   base `Items'
a4.h:32: warning:   when initialized here
a4.h: In constructor `Book::Book(int, std::string, int, std::string, int)':
a4.h:48: warning: `Book::numPages' will be initialized after
a4.h:52: warning:   base `Items'
a4.h:52: warning:   when initialized here
a4.h: In constructor `CD::CD(int, std::string, int, std::string, int)':
a4.h:66: warning: `CD::numSongs' will be initialized after
a4.h:70: warning:   base `Items'
a4.h:70: warning:   when initialized here
>Exit code: 0

Ответы [ 3 ]

28 голосов
/ 02 мая 2010

Когда вы объявляете переменные-члены в классе, они инициализируются в том порядке, в котором вы их объявляете. Но вы можете написать их в любом порядке в списке инициализатора вашего конструктора. Например,

struct foo {
   int a;
   int b;

   foo(): b(5), a(3) {}
};

создаст a и , затем b, даже если кажется, что вы инициализируете их в другом порядке.

Компилятор выдает предупреждение, потому что вы можете обмануть себя в написании неверного кода. Например,

struct foo {
    int a;
    int b;

    foo(): b(5), a(b) {}
};

значение a будет неопределенным.

6 голосов
/ 02 мая 2010

Вам нужно взглянуть на ваши конструкторы и списки инициализации членов. Сложно сказать, не видя код, но происходит то, что у вас есть такой код: -

class my_class : public base1, public base2
{
    public:
        my_class();

    private:
        member1 member1_;
        member2 member2_;
}

my_class::my_class() 
    : member2_(...)
    , member1_(...)
    , base2_(...)
    , base1_(...)
{ }

Это выдаст аналогичные предупреждения. Причина в том, что в C ++ конструктор всегда создает базовые классы в порядке, показанном в списке базовых классов (base1, за которым следует base2), затем он создает переменные-члены сверху вниз в определении класса. Это происходит без учета порядка, который вы указываете в списке инициализации вашего члена - этот порядок игнорируется, но если он не соответствует некоторым компиляторам (включая ваш, кажется), предупредит вас об этом.

Кстати, причина, по которой он делает это, заключается в том, что в C ++ существует строгое требование вызова деструкторов в обратном порядке конструкторов, поэтому, если бы он делал вещи в порядке списков инициализации членов, он должен был бы каким-то образом "запомнить" какой конструктор был вызван так, чтобы он мог вызывать деструкторы в правильном порядке. Он этого не делает, а просто всегда использует один и тот же порядок.

3 голосов
/ 02 мая 2010

Когда вы инициализируете члены класса в конструкторе, инициализируйте их в том же порядке, в котором они объявлены. E.g.:

class Foo {
  public:
    int a;
    int b;
    Foo() : a(0), b(0) {}
};

В конструкторе Foo() переключение порядка a и b приведет к вашим предупреждениям. То же самое касается инициализации базовых классов (чьи конструкторы, если они вызываются явно, должны вызываться перед инициализаторами любого элемента данных).

...