2010-05-02 93 views
5

我有一套代码,它模仿了一个基本的图书馆编目系统。有一个名为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 

回答

28

当您在一个类中声明成员变量时,它们将按照您声明的顺序进行初始化。但是你可以在你的构造函数的初始化列表中以任何顺序编写它们。例如,

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的值将是未定义的。

+0

非常感谢你 – silent 2010-05-02 05:05:41

+0

很好的答案,谢谢。 – 2013-04-10 05:58:27

3

当您在构造函数中初始化类成员时,请按照声明它们的相同顺序对它们进行初始化。例如: -

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

Foo()构造,交换的ab顺序会导致你的警告。初始化基类也是一样的(如果在任何数据成员初始化之前调用它的构造函数,则应该调用它的构造函数)。

6

你需要看看你的构造函数和成员初始化列表。这是棘手的说没有看到代码,但正在发生的事情是,你有这样的代码: -

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++严格要求析构函数按照构造函数的相反顺序调用,所以如果它按照成员初始化列表的顺序执行,它必须以某种方式“记住“哪个构造函数已被调用,以便它可以按正确的顺序调用析构函数。它不这样做,而是总是使用相同的顺序。