1

我在 C++ 中有一个class调用。Tracer在我的Tracer.h文件中,我有:

class Tracer{

public:
    // not useful to the question.
private:
    Logger *m_logger;
    const char *m_who;
    const char *m_fileName;
    const void * m_theObject;
    int m_lineNum;
    int m_log_level;
}

Tracer.cpp我有:

Tracer::Tracer(
        Logger *logger,
        const void *theObject,
        const char *who,
        const char *file,
        int line,
        int log_level
        ) :
        m_logger(logger),
        m_who(who),
        m_fileName(file),
        m_lineNum(line),
        m_theObject(theObject),
        m_log_level(log_level)
{
  // more implementation which is not useful to the problem.

问题是,当我初始化时m_theObject(theObject),我收到以下警告

/home/pribeiro/workspace/Tracer.h:80: warning:   'const void* Tracer::m_theObject'
/home/pribeiro/workspace/Tracer.cpp:27: warning:   when initialized here

Tracer.h:80是中的声明m_theObject并且Tracer.hTracer.cpp:27m_theObject(theObject。在我的编译级别中,警告被视为错误。为什么编译器抱怨const void *指针的初始化?

4

3 回答 3

4

这还不是全部警告。它实际上是在警告m_lineNum并且m_theObject正在以错误的顺序初始化(请参阅Member fields, order of construction):

Tracer.h:80: warning:   'const void* Tracer::m_theObject' is initialized before 'int Tracer::m_lineNum'
Tracer.cpp:27: warning:   when initialized here

解决方法是交换初始化顺序或定义顺序:

Tracer::Tracer(
        Logger *logger,
        const void *theObject,
        const char *who,
        const char *file,
        int line,
        int log_level
        ) :
        m_logger(logger),
        m_who(who),
        m_fileName(file),
        m_theObject(theObject),    // here
        m_lineNum(line),           // and here
        m_log_level(log_level)
{
  // more implementation which is not useful to the problem.
于 2012-08-01T12:48:30.113 回答
3

有时,当成员在成员初始化列表中的初始化顺序与在标头中声明的顺序不同时,编译器会发出警告。我以前见过 g++ 这样做。如果您重新排序初始化列表,使其与头文件中出现的成员顺序相同,您应该会看到此警告消失。

于 2012-08-01T12:47:26.913 回答
0

这里的问题是,根据 C++ 标准,无论您在构造函数中给出的顺序如何,成员变量始终始终)按照声明的顺序进行初始化。

编译器会很好地警告您不合适,因为您可能会引入意外的依赖链。


例子:

struct Foo {
    int _1, _2, _3;

    Foo() : _3(_2+_1),  // Third initialization
            _2(_1+_1),  // Second initialization
            _1(1)       // First initialization
    {}
};

#include <iostream>
int main () {
    Foo f;
    std::cout << f._1 << f._2 << f._3 << '\n';
}

输出:

123

但是成员初始化器的顺序可能会让维护者认为他可以做得更好:

struct Foo {
    int _1, _2, _3;

    Foo() : _3(3),
            _2(_3-1),
            _1(_2-1)
    {}
};

#include <iostream>
int main () {
    Foo f;
    std::cout << f._1 << f._2 << f._3 << '\n';
}

人们可能会再次期望在该构造函数中首先初始化的123输出_3。但这不是真的:

./teh_program
13451434436167553
./teh_program
134514344118742913
./teh_program
13451434495068033

结果是完全不可预测的,多次运行甚至无需重新编译就会给出不同的结果。而编译器就是为了防止这样的意外。

于 2012-08-01T12:57:20.423 回答