【问题标题】:Multilevel hierarchy with virtuality prevents casting function pointers具有虚拟性的多级层次结构可防止转换函数指针
【发布时间】:2016-10-16 18:40:34
【问题描述】:

我创建了一些类层次结构,其中的基类(在以下示例中:clA)定义了从executor 例程调用的函数指针。反过来,作为回调传递executor 的代码不知道它在哪种类型的派生对象上运行(clB 只是其中之一)。如果派生类没有实现某些函数,它不会强制转换为函数指针,并且在调用 executor 时不会发生任何事情。还有一些虚函数(clA 实际上是纯虚函数)。我的类看起来与此类似(无法呈现实际代码,因此我创建了简化的演示):

class clA
{
protected:
    INT_PTR(__stdcall clA::*Fn1)(int);
    INT_PTR(__stdcall clA::*Fn2)(int);
    static INT_PTR CALLBACK executor(UINT operation, int opData, clA *ptr = NULL)
    {
        switch (operation)
        {
        case 1:
            if (ptr->Fn1)
            {
                typedef INT_PTR(__stdcall clA::*FPtr)(int);
                FPtr funcPtr = ptr->Fn1;
                return (ptr->*funcPtr)(opData);
            }
            break;
        case 2:
            if (ptr->Fn2)
            {
                typedef INT_PTR(__stdcall clA::*FPtr)(int);
                FPtr funcPtr = ptr->Fn2;
                return (ptr->*funcPtr)(opData);
            }
            break;
        }
    }
public:
    clA() { Fn1 = NULL; Fn2 = NULL; }
    virtual BOOL vrt(void) = 0;
};

class clB : public clA
{
    INT_PTR __stdcall ImplFn1(int) { return 0; }
    INT_PTR __stdcall ImplFn2(int) { return 0; }
public:
    void testing(void);
    clB()
    {
        Fn1 = reinterpret_cast <INT_PTR(__stdcall clA::*)(int)> (&clB::ImplFn1);
        Fn2 = reinterpret_cast <INT_PTR(__stdcall clA::*)(int)> (&clB::ImplFn2);
    }
    BOOL vrt(void) { return FALSE; };
};

到目前为止一切正常,直到今天我决定我需要基类 clA 来继承其他类,让它成为 clExtra,所以我做了以下更改:

class clExtra
{
public:
   static int x;
};

//now class clA is deriving from clExtra
class clA : public clExtra

问题

现在我有以下编译错误:

inheritancetest.h(49): error C2440: 'reinterpret_cast' : cannot convert from 'INT_PTR (__stdcall clB::* )(int)' to 'INT_PTR (__stdcall clA::* )(int)'
Pointers to members have different representations; cannot cast between them

我真的不明白它们是如何突然变成不同的表示的。 MSDN 的可能 C2440 原因示例不适用。奇怪的是,如果我从 clA 类中删除任何虚拟性,我也可以让它编译。如果有人了解可能导致我无法投射的原因,我将永远感激您的解释。

【问题讨论】:

    标签: c++ casting member-function-pointers


    【解决方案1】:

    我认为这是 VC++ 中的错误。它在 gcc 中 compiles successfully

    static_cast 足以完成这种类型的转换。

    我发现 VC++ 在使用 static_cast 而不是 reinterpret_cast 时不会报错。

    【讨论】:

    • 你说得对,我可以用 static_cast 替换所有演员表,但我想避免它,因为它们太多了......重新设计 1000 个构造函数仍然比重新工作要快不过,请等待可能的错误确认。我会解决的,同时也许有类似经验的其他人会阅读这篇文章
    • @Kitet 你为什么不想使用static_cast?表现?我认为在这种情况下不会插入额外的指令,因为它们不需要。如果您想 100% 确定,请查看生成的程序集。
    • 你一定是误会了什么。我将它们全部切换为静态,花了 2 个小时完成所有构造函数和一些测试。
    猜你喜欢
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2019-10-21
    • 1970-01-01
    相关资源
    最近更新 更多