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

问题描述

我正在研究用 C++ 编写的多平台代码(Windows、Linux 和 Mac)。今天我不得不找到一个问题,这个问题只在windows中出现,看起来是编译器问题。具有多个基类的类调用基类方法,但传递错误的值作为 this。

我写了一个简短的 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 编译的可执行文件显示 y=3 用于调用 base2::printy() 和 base2::print()。

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<derived>。但无论如何,没有编译器会抱怨缺少模板参数,但是 vs2005 会默默地生成代码,将错误的 this 指针传递给被调用的方法。

所以,这是我的问题:

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

标签: c++visual-studiovisual-c++multiple-inheritanceundefined-behavior

解决方案


推荐阅读