1# warning: ... will be initialized after... / ... warning: when initialized here [1][2]
示例:
class foo {
//declaration
int i;
int j;
public:
//constructor & its initializer
foo(int val): j(val), i(j) {}
};
C++规定:构造函数初始化列表(constructor's initializer)中,编译器对成员初化的实际顺序是由成员的声明/定义顺序决定的,而与初始化列表中成员的排列顺序无关。在这个示例中,声明的顺序是先i后j,那么按根据这个规定,编译器也会先初始化i,再初始化j。这样上面的示例
foo(int val): j(val), i(j) {}
在编译过程中首先就是用一个还未初始化的成员j来初始化成员i,这当然会给程序带来bug。所以,编译器友好地给出了上面那条警告信息。 解决办法自然是调整初始化顺序,与声明顺序一致:
foo(int val): i(val), j(val) {}
Ref.:
[1] C++ Primer 中文版 第4版P389
2# waring: virtual … was hidden by … [3][4][5]
示例:
class Base {
public:
virtual int fcn();
};
class Derive:public Base {
public:
// For clearing the warning, uncomment:
//using Base::fcn;
// However, it's not a good idea to do this (using declaration) if this codes are in any header file.
// Or, uncomment:
//int fcn();
int fcn(int);
};
int main()
{
std::cout<<"Yeah\n";
return 0;
}
编译时,如果g++ 或Makefile中加了警告选项:-Woverloaded-virtual,则会出现上面那条的警告信息。 如:
$ g++ overloadBaseMember.cc -Woverloaded-virtual
overloadBaseMember.cc:33: warning: `virtual int Base::fcn()' was hidden
overloadBaseMember.cc:43: warning: by `int Derive1::fcn(int)'
overloadBaseMember.cc:33: warning: `virtual int Base::fcn()' was hidden
overloadBaseMember.cc:43: warning: by `int Derive1::fcn(int)'
这是因为派生类Derive在继承基类Base后,其类作用域内重载了基类中的虚函数fcn,那么在此作用域内原先基类的fcn()函数将被屏蔽/不可见。
解决办法是在派生类中使用using声明(using declaration)来重新声明基类中所有名为fcn的函数(9行),这样使其可见。但此法建议不要用在头文件中;
另一种办法是在派生类Derive中直接重定义Base类中的fcn()函数(12行)。
当然,你要干脆去掉 -Woverloaded-virtual 选项来忽略这类警告,那也是可以的。
至于这样做有什么风险,以及C++为什么要预留这种警告?遗憾本君也未弄清,待后续文章更新中再作理解。(亦盼大侠指点迷津)
Ref.:
[3] C++ Primer 中文版 第4版P501
3# warning: statement has no effect
示例:
int i=0, N=100;
for( i; i < N; i++) {}
正确示例:
int i=0, N=100;
for( ; i < N; i++) {}
//or
for(i=0; i<N; i++) {}
要么就必须对for循环的第一个参数做点什么(定义、初始化/赋值),要么就空着不传第一个参数。否则,将出现3#的警告信息。
本文介绍了C++编译过程中常见的三种警告:初始化列表次序错误、虚函数被隐藏以及无效语句。针对这些问题,分别提供了对应的解决策略,帮助开发者提升代码质量。
2432

被折叠的 条评论
为什么被折叠?



