5

我有一组代码,它模仿了一个基本的图书馆编目系统。有一个名为 items 的基类,其中定义了通用 id、title 和 year 变量以及 3 个其他派生类(DVD、Book 和 CD)。

基础[物品]

派生的 [DVD,Book,CD]。

程序运行,但是我收到以下警告,我不知道如何解决这些问题。

>"C:\Program Files\gcc\bin/g++" -Os -mconsole -g -Wall -Wshadow -fno-common mainA4.cpp -o mainA4.exe
在 mainA4.cpp:5 包含的文件中:
a4.h:在构造函数“DVD::DVD(int, std::string, int, std::string)”中:
a4.h:28: 警告: `DVD::director' 将在之后初始化
a4.h:32:警告:基础“项目”
a4.h:32:警告:在此处初始化时
a4.h:在构造函数`Book::Book(int, std::string, int, std::string, int)'中:
a4.h:48: 警告: `Book::numPages' 将在之后初始化
a4.h:52:警告:基础“项目”
a4.h:52:警告:在此处初始化时
a4.h:在构造函数`CD::CD(int, std::string, int, std::string, int)'中:
a4.h:66: 警告: `CD::numSongs' 将在之后初始化
a4.h:70:警告:基础“项目”
a4.h:70:警告:在此处初始化时
>退出代码:0
4

3 回答 3

28

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

struct foo {
   int a;
   int b;

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

将构造aand then b,即使看起来您正在以其他顺序初始化它们。

编译器会发出警告,因为您可以欺骗自己编写不正确的代码。例如,

struct foo {
    int a;
    int b;

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

的值a将是未定义的。

于 2010-05-02T04:44:32.960 回答
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++ 有一个严格的要求,即以构造函数的相反顺序调用析构函数,因此如果它按照成员初始化列表的顺序执行操作,它必须以某种方式“记住”哪个构造函数具有被调用以便它可以以正确的顺序调用析构函数。它不这样做,而是总是使用相同的顺序。

于 2010-05-02T04:49:13.317 回答
3

在构造函数中初始化类成员时,按照声明它们的顺序初始化它们。例如:

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

在构造函数中,切换andFoo()的顺序会导致您的警告。初始化基类也是如此(如果显式调用其构造函数,则应在任何数据成员初始化程序之前调用)。ab

于 2010-05-02T04:45:12.853 回答