是否在不提供模板参数的情况下调用模板基类方法未定义行为?

时间:2018-08-16 10:11:22

标签: c++ visual-studio visual-c++ multiple-inheritance undefined-behavior

我正在研究用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默默地生成了将错误的this指针传递给被调用方法的代码。

所以,这是我的问题:

这是“仅仅是” vs2005中的编译器错误,还是这种未定义的行为,没有编译器会抱怨?

0 个答案:

没有答案