0

我遇到了 MFC C++ 多态性,这是我的问题:

我有一个类,比如说 A,它实现了很多有用的东西,但是我需要从中实例化的每个对象都需要一些定制,所以我决定派生我的每个类(例如:A1、A2... )。现在,这些对象的初始化需要一些对所有子类都相同的操作,所以我构建了一个静态方法来完成这项任务,问题就来了:

void CFastInit::FastGrid( const CStatic &stPosition, A *pGrid, UINT nID, CWnd *pWnd )
{
    stPosition.GetClientRect( rctGriPos );
    stPosition.MapWindowPoints( pWnd, rctGriPos );
    pGrid->Create( WS_CHILD | WS_VISIBLE, rctGriPos, pWnd, nID );
    pGrid->SetWholeRowSel();
}

从调试器我可以看到 pGrid 是正确的类型( A1, A2... ),但是调用:

pGrid->Create(

对 A::Create 而不是 A1::Create 或 A2::Create 完成。有解决方法吗?

4

3 回答 3

3

似乎你有一个静态功能FastGrid()。请注意,此函数由基类的所有对象以及从基类派生的任何类的所有对象共享。

在此函数中,您将获得一个指向基类的指针作为参数: A *pGrid,然后对该指针进行函数调用:pGrid->Create()

现在,如果pGrid指向派生类对象,如果你想拥有多态性,你需要Create()函数是。virtual如果它不是虚拟的,则Create()基类的函数将始终被调用。

可能你想要这样的东西:

class base
{
public:
    static void foo( base * ptr)
    {
        ptr->bar();
    }
    virtual void bar()
    {
        std::cout << "base class bar() call" << std::endl;
    }
};

class derived : public base
{
    virtual void bar()
    {
        std::cout << "derived class bar() call" << std::endl;
    }
};

int main(int argc, char *argv[])
{
    base::foo( new derived() );
}

输出:

derived class bar() call

如果删除virtual关键字,输出将是

base class bar() call

这就是你现在所拥有的。另请注意,我的示例中的静态函数也可以这样调用:derived::foo( new derived() );,这不会改变任何东西。

于 2012-08-01T13:04:02.547 回答
0

这是因为 pGrid 的类型为“A”。您可以使用类型检查并将其强制转换为使用您想要的方法。

于 2012-08-01T13:02:29.830 回答
0

在您的情况下,忘记添加 virtual 关键字可能是根本原因,但是,如果您从 ctor 调用实例方法,则虚拟函数也不起作用,因为编译器将确保虚拟表指针在 ctor 的范围内基类属于基类,派生类也是。

而且,除了虚函数,模板也可以用来达到类似的效果,就像你在 ATL 中看到的很多例子一样

于 2012-08-01T13:30:56.330 回答