我正在研究用C ++编写的多平台代码(Windows,Linux和Mac)。今天,我不得不找到一个仅在Windows中困扰的问题,看起来像是编译器问题。具有多个基类的类将调用基类方法,但是这样会传递错误的值。
我写了一个简短的C ++示例来重现此问题:
#include <stdio.h>
class base1
{
public:
int x;
base1(int x):x(x)
{
printf("%s(): this=%p x=%d\n", __FUNCTION__, this, x);
}
void printx()
{
printf("%s(): this=%p x=%d\n", __FUNCTION__, this, x);
}
void print()
{
printf("%s(): this=%p\n", __FUNCTION__, this);
printx();
}
};
template <class T>
class base2
{
public:
int y;
base2(int y):y(y)
{
printf("%s(): this=%p y=%d\n", __FUNCTION__, this, y);
}
void printy()
{
printf("%s(): this=%p y=%d\n", __FUNCTION__, this, y);
}
void print()
{
printf("%s(): this=%p\n", __FUNCTION__, this);
printy();
}
};
class derived: public base1, public base2<derived>
{
public:
int z;
derived()
: base1(1)
, base2(2)
, z(3)
{
printf("%s(): this=%p z=%d\n", __FUNCTION__, this, z);
}
void printz()
{
printf("%s(): this=%p z=%d\n", __FUNCTION__, this, z);
}
void print()
{
printx();
base1::printx();
base1::print();
printf("-----\n");
printy();
base2::printy(); // <--- this call does not work with vs2005
base2::print(); // <--- and this call doesn't work, too.
base2<derived>::printy();
base2<derived>::print();
printf("-----\n");
printz();
}
};
int main(int argc, char *argv[])
{
derived d;
printf("-----\n");
d.print();
}
代码在Windows(使用vs2005和vs2010),Linux(g ++(Gentoo 6.4.0-r1 p1.3)6.4.0)和MacOS(Apple LLVM版本8.1.0(clang-802.0)上,没有任何警告的情况下进行编译。 42))。
代码应始终打印x = 1,y = 2或z = 3。
但是vs2005编译的可执行文件显示,对base2 :: printy()和base2 :: print()的调用为y = 3。
base1::base1(): this=0018FF3C x=1
base2<class derived>::base2(): this=0018FF40 y=2
derived::derived(): this=0018FF3C z=3
-----
base1::printx(): this=0018FF3C x=1
base1::printx(): this=0018FF3C x=1
base1::print(): this=0018FF3C
base1::printx(): this=0018FF3C x=1
-----
base2<class derived>::printy(): this=0018FF40 y=2
base2<class derived>::printy(): this=0018FF44 y=3 <--------
base2<class derived>::print(): this=0018FF44
base2<class derived>::printy(): this=0018FF44 y=3 <--------
base2<class derived>::printy(): this=0018FF40 y=2
base2<class derived>::print(): this=0018FF40
base2<class derived>::printy(): this=0018FF40 y=2
-----
derived::printz(): this=0018FF3C z=3
当base2是常规类而不是类模板时,该调用将按预期工作。
由于base2是类模板,所以基类的全名不是base2而是base2
这是“仅仅是” vs2005中的编译器错误,还是这种未定义的行为,没有编译器会抱怨?