我遇到了MFC C ++多态,这是我的问题:
我有一个类,比如A,它实现了许多有用的东西,但是我需要从中实例化的每个对象都需要一些自定义,所以我决定派生我的每个类(ig: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。有解决方法吗?
答案 0 :(得分:3)
似乎你有一个静态函数FastGrid()
。请注意,此函数由基类的所有对象共享,和从base派生的任何类的所有对象。
在此函数中,您将获得指向基类的指针作为参数: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() );
,它不会改变任何东西。
答案 1 :(得分:0)
这是因为pGrid的类型为“A”。您可以使用类型检查并将其强制转换为强制它使用您想要的方法。
答案 2 :(得分:0)
忘记添加虚拟关键字可能是你的情况下的根本原因,但是,如果从ctor调用实例方法,虚函数也不起作用,因为编译器将确保范围内的虚拟表指针基类的ctor属于基类,因此它与派生类有关。
除了虚拟功能之外,该模板还可用于达到与您在ATL中看到的大量示例类似的效果