以下代码在VS 2013 Release/Debug下产生不同的结果。

4

这是VS 2013编译器的一个bug吗?
以下代码在debug和release模式下产生不同的结果。
在debug模式下,结果符合预期,但在release模式下,结果为"A"。

#include <cstdio>

struct A
{
    virtual void* getClass() { return A::ID; };
    static void ID(){};
};

struct B : public A
{
    virtual void* getClass() { return B::ID; };
    static void ID(){};
};

struct C : public A
{
    virtual void* getClass() { return C::ID; };
    static void ID(){};
};


int main(int argc, char *argv[])
{
    A* d = new C;

    if (d->getClass() == A::ID)
    {
        printf("A");
    }
    else if (d->getClass() == B::ID)
    {
        printf("B");
    }
    else if (d->getClass() == C::ID)
    {
        printf("C");
    }

}

1
嗯...这甚至不应该编译,你不能将函数指针隐式转换为void* - Mat
任何指针都应该转换为void, 如果我在每个类中将ID更改为: static char ID(){ return "CLASS"; }; 似乎没问题,所以看来具有相同实现的函数被视为相同的函数,但这不是标准违规吗? - kamerunka
1
该函数是静态的,它不是成员指针。 - kamerunka
@LightnessRacesinOrbit 我认为这并不是真正的重复,那个问题只解决了一半的问题。这个问题的一部分是非符合转换,这不是那个重复的一部分。 - Shafik Yaghmour
显示剩余3条评论
1个回答

1
由于编译器的优化导致这种情况发生。
似乎编译器是否应该执行此类优化是有争议的不同函数是否具有不同的地址?

typeid

更传统的方法是使用typeid来验证运行时类型。请注意,您需要解除指针引用以获取派生类的类型。
if (typeid(*d) == typeid(A))
{
    printf("A");
}
else if (typeid(*d) == typeid(B))
{
    printf("B");
}
else if (typeid(*d) == typeid(C))
{
    printf("C");
}

禁用优化

然而,由于 /OPT:ICF 可以合并相同的数据或函数,它可能会改变出现在堆栈跟踪中的函数名称。

您可以在发布时使用 /OPT:NOICF 以防止该行为。


此外,您可以看到实际上以不同的方式实现函数会使其按照您的预期工作。

示例代码

#include <string>

struct A
{
    virtual std::string getClass() { return A::ID(); }
    static std::string ID(){ return "A"; }
};

struct B : public A
{
    virtual std::string getClass() { return B::ID(); }
    static std::string ID(){ return "B"; }
};

struct C : public A
{
    virtual std::string getClass() { return C::ID(); }
    static std::string ID(){ return "C"; }
};

int main(int argc, char *argv[])
{
    A* d = new C;

    if (d->getClass() == A::ID())
    {
        printf("A");
    }
    else if (d->getClass() == B::ID())
    {
        printf("B");
    }
    else if (d->getClass() == C::ID())
    {
        printf("C");
    }
}

是的,我已经弄清楚了,但这不是违反标准吗? - kamerunka
“静态A :: ID,B :: ID和C :: ID函数生成完全相同的代码,因此它们可以由单个函数表示。” 呃...不,我不这么认为。 我承认这是有争议的(https://dev59.com/pF8d5IYBdhLWcg3wtz8Q)。 - Lightness Races in Orbit
请查看不同的函数是否具有不同的地址? - Shafik Yaghmour
实际上,函数指针更多地涉及“在哪里”而不是“什么”。因此,如果它们存储在相同的内存地址,则可以相等。我认为标准并不要求将函数存储在不同的位置。 - user3528438
@LightnessRacesinOrbit 那是一个好链接,谢谢。 - James Adkison
1
@ShafikYaghmour 这个很好知道,谢谢! - user3528438

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接