dynamic_cast在做downcast的时候出了问题.

dot99 2004-06-29 06:14:18
问题:
ChdProcWinDlg *pParent = dynamic_cast<ChdProcWinDlg*>(pwnd->GetParent());
有错吗?
为什么我都得到null
直接强转就ok
ChdProcWinDlg *pParent = (ChdProcWinDlg*)pwnd->GetParent();
(运行期正确)

环境:
这个是在线程里面, 需要使用到窗口类中的方法
pwnd 是通过 DWORD WINAPI ThreadFunc(LPVOID)中传过去的参数用reinterpret_cast转换得到:
CDlgPC * pwnd = reinterpret_cast<CDlgPC*>(lpParam);
CDlgPC是ChdProcWinDlg的子窗口

牢骚:
CWnd => ChdProcWinDlg 是一个 downcast啊~
难道是我对dynamic_cast理解有偏差?
还是GetParent();给我的不是CWnd*
昏了~~

附加:
同样的问题, 出在下面:
(1)
CWnd *pwnd = CWnd::FromHandle(GlobalVar.hwnd_main);
Dlg_Main *pdlg = DYNAMIC_DOWNCAST(Dlg_Main, pwnd);
运行期正确
(环境: 用在dll的函数里面, 需要修改到hwnd_main这个窗口内的一些数据)

(2)
Dlg_Main *pdlg = DYNAMIC_DOWNCAST(Dlg_Main, GetParent());
运行期正确
(环境: 用在Dlg_Main子窗口内)

(3)
ChdProcWinDlg *pParent = DYNAMIC_DOWNCAST(ChdProcWinDlg, pwnd->GetParent());
运行期错误(NULL)
(环境同最上面的一样)


开发工具: VC.NET 2003

ps:不知道该po在哪边, 属于MFC还是C++的问题?
...全文
566 点赞 收藏 57
写回复
57 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
dot99 2004-07-09
up一个~~~
回复
dot99 2004-07-08
最后一顶, 没人给个令人信服的答案我就转非技术了~~~~~~
奶油狗不给我转MFC
回复
dot99 2004-07-08
原来可以自己转~~~~~~~(以前转没成功,老是500, 就以为从来就转不成.....)
回复
皮皮爸 2004-07-08
不太懂,幫你頂一下
回复
dot99 2004-07-06
天亮顶一个~~~~
google上我勾不到~~~~
哪个来说说
说安逸了就揭帖~~~~^_^
回复
dot99 2004-07-05
其实,我好想有人给我说MFC的实现是用特别的方法,且不支持RTTI
记得jjhou的<MFC深入潜出>里面说过, 当时MFC并不支持C++标准的RTTI, 是用RUNTIME CLASS的识别链表来实现RTTI
结果, 我使用其提供的DYNAMIC_DOWNCAST, 还是不行(在线程里面)
但是疑问的地方, 要是不行,那么请都给我不行, 结果, 却在类成员函数里面两个(dynamic_cast, DYNAMIC_DOWNCAST)都通过了.
回复
dot99 2004-07-05
用MFC提供的宏DYNAMIC_DOWNCAST情况也一样
回复
dot99 2004-07-05
CWnd* CWnd::GetParent();
CDlgPC* pwnd;
CDlgPC是从CWnd继承下来的一个类
ChdProcWinDlg是从CWnd继承下来的一个类
pwnd->GetParent()指向ChdProcWinDlg的实例
回复
changeme 2004-07-05
GetParent到底返回的是什么类型?
cwnd pwnd和ChdProcWinDlg之间的类关系是怎么样的?

回复
dot99 2004-07-05
加到150分了
参与讨论的都分分
回复
dot99 2004-07-05
to changeme(笑熬漿糊)
static_cast当然可以~~
我现在问的是我的dynamic_cast在上面两个地方中为什么一个可以,一个不可以~~
而且据你所说, 必须确定pBase指向的必须是子类对象才可以downcast. 这点, 我已经注意到了, 看上贴, 在类成员函数中用dynamic_cast对GetParent()转换没问题, 却在外面用这个转换的时候出了问题, why?
回复
dot99 2004-07-05
to Wyhshp(阿呆):
试试看:
ChdProcWinDlg *pParent = dynamic_cast<ChdProcWinDlg*>(pwnd);

错误~~~类型不对头

to changeme(我本楚狂人)
编译是通过了的, 说明CWnd的确是个多态类(至少在MFC本身代码RTTI可行)

to lanzhengpeng2(兰征鹏)
〉MFC里面可以,我却不行:
首先,前提是你要打开RTTI。 ---> 打开了
其次,type_info并没有作为dll的导出部分,所以,MFC内部可以使用type_info,但是使用MFC的代码却不知道其type_info --> 比较赞同的观点, 但需要高手来证实

回复
Wyhshp 2004-07-05
class CA
{
public:
virtual void foo(){}
};
class CB: public CA
{
virtual void foo1(){}
};


int main()
{

CB *pCB = new CB;
pCA = dynamic_cast<CA*>(pCB); // 正确用法.
CA *pCA = new CA;
CB *pCB1 = dynamic_cast<CB*>(pCA); // 错误用法.

return ;
}

正确:
ChdProcWinDlg *pParent = static_cast<ChdProcWinDlg*>(pwnd->GetParent());
试试看:
ChdProcWinDlg *pParent = dynamic_cast<ChdProcWinDlg*>(pwnd);


回复
lanzhengpeng2 2004-07-05
〉MFC里面可以,我却不行:
首先,前提是你要打开RTTI。
其次,type_info并没有作为dll的导出部分,所以,MFC内部可以使用type_info,但是使用MFC的代码却不知道其type_info
回复
changeme 2004-07-05
有个地方没讲清楚
用dynamic_cast进行downcast时,父类必须是多态类,也就是说,父类必须至少有一个
virtual成员函数。
class A{
public:
void foo(){...}
};
class B:public:A
{...};

int main()
{
A* a = new A;
B* b = new B;
b = dynamic_cast<B*>(a); //编译不通过,试着在class A声明中插入virtual函数看看
return 0;
回复
dot99 2004-07-05
void CDlgPC::start(void)
{
products_ = 0;
mx_ = 1;
full_mx_ = 0;
empty_mx_ = m_maxproducts;

GetDlgItem(IDC_EDIT_MAXPRODUCT)->EnableWindow(FALSE);

mx = new CSemaphore(1, 1);
full_mx = new CSemaphore(0, m_maxproducts);
empty_mx = new CSemaphore(m_maxproducts, m_maxproducts);

/////////////////////////////////////////////
ChdProcWinDlg *pParent = dynamic_cast<ChdProcWinDlg*>(GetParent());
assert(pParent); // success
/////////////////////////////////////////////


pParent->logtomsg("** PRODUCER-CONSUMER Problem TEST **");

m_hProducer = CreateThread(NULL, 0, producer, this, 0, NULL);
// here pass "this" to producer(LPVOID)
m_hConsumer = CreateThread(NULL, 0, consumer, this, 0, NULL);
}

DWORD WINAPI producer(LPVOID lpParam)
{
char buf[256];
CDlgPC *pwnd = reinterpret_cast<CDlgPC*>(lpParam);
assert(pwnd);
/////////////////////////////////////////////
ChdProcWinDlg *pParent = dynamic_cast<ChdProcWinDlg*>(pwnd->GetParent());
assert(pParent); // 0x00000000 why? here both static_cast and reinterpret_cast got no problem (of cause)
/////////////////////////////////////////////

//....
}

回复
changeme 2004-07-05
GetParent方法是返回一个ChdProcWinDlg类型的指针,还是返回一个CWnd类型的指针,但是指向ChdProcWinDlg对象?
第一种情况,绝对OK,除非编译器对ISO的支持不好。
第二种情况,不可以,dynamic_cast只能用于多态。

我猜你所说的是第二种情况。
回复
dot99 2004-07-04
//////quote////////
b = dynamic_cast<B*>(a); //小心

你必须知道a虽然是A*类型的,但是实际上在程序中,他指向了一个B*的对象。
否则,dynamic_cast返回值为0。
///////////////////

我确定pwnd->GetParent()得到的这个CWnd*指向ChdProcWinDlg


//////quote////////
B b;
A *pa =&b;
B *pb = dynamic_cast<B*><pa>; //SUCCESS
///////////////////

当然success, 见前面的程序

我说过在CDlgPC::func()中
dynamic_cast<ChdProcWinDlg*>(GetParent());
正确

不过在一个线程函数里面DWORD WINAPI ThreadFunc(LPVOID lpParam)里面
CDlgPC* pwnd = reinterpret_cast<CDlgPC*>(lpParam);
dynamic_cast<ChdProcWinDlg*>(pwnd->GetParent()); //这里不行, 为NULL
lpParam是在CDlgPC里面传过去的this指针

这样有什么区别吗?
如果有的话, 区别在哪里, 错误在哪里?



回复
changeme 2004-07-04
楼主,给分吧~
回复
bluestone 2004-07-04
dynamic_cast<A type>(B type)
如果时downcast的哈,dynamic_cast会检查是否B type真的指向A type的对象,如果不是,会返回0

例如
class A{};
class B:public A{};

....
B b;
A *pa =&b;
B *pb = dynamic_cast<B*><pa>; //SUCCESS

....
A a;
A *pa = &a;
B *pb = dynamic_cast<B*><pa>; //get NULL point
回复
相关推荐
发帖
非技术区
创建于2007-09-28

1.5w+

社区成员

C/C++ 非技术区
申请成为版主
帖子事件
创建了帖子
2004-06-29 06:14
社区公告
暂无公告