多态问题的请教?

yaoike 2007-10-28 12:03:50
大家好,想请教大家一个方法的设计问题?谢谢你的解答。
我有几个类,如下:

class CMessage
{
public:
int m_nMessageId;
};

class CAuthMsg : public CMessage
{
public:
int m_nProdId;
};

class CTrafficAccoutMsg : public CMessage
{
public:
int m_nProdId;
};

class CProcessMsg
{
public:
void processMsg(CMessage *pMsg);
};

现在问题是,我如何实现processMsg()这个方法,让该方法可以识别调用该方法时,实参传进来的是CTrafficAccoutMsg指针还是CAuthMsg指针,然后对它们进行一系列的处理后,再返回指针,请问我该如何设计这个方法,我希望把它设置成通用一点。谢谢指教!

void CProcessMsg::processMsg(CMessage *pMessage)
{
switch (pMessage->m_nMessageId)
{
case ID_Auth:
CAuthMsg *pMsg = new CAuthMsg;
... // 这里对CAuthMsg对象指针pMsg的数据成员m_nProdId 进行一系列的处理. 例如这句:pMsg->m_nProdId = 8;
break;
case ID_TrafficAccout:
CTrafficAccoutMsg *pMsg = new CTrafficAccoutMsg;
... // 这里对CTrafficAccoutMsg 对象指针pMsg的数据成员m_nProdId 也进行一系列的处理.例如都是这句:
// pMsg->m_nProdId = 8;因为处理与上面的处理相同,我希望把这一块单独提取出来,请问我该如何做?
break;
default:
break;
}
// 如果把 pMsg->m_nProdId = 8;这句放在这里的话,就跳出了 pMsg指针的作用域,我在这个问题上想了一两天,都想不
// 出一个头绪来,各位可以指点一下吗?注:因为类已经封装好,所以,暂时不考虑把 m_nProdId 放到 类CMessage中。请
// 在保持现有类结构的情况下,把这个方法的实现改写一下可以吗?至于这个方法processMsg()的形参个数,返回值等都可
// 以自由定义。非常感谢!!!
}




...全文
457 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
scq2099yt 2007-10-30
  • 打赏
  • 举报
回复
ding
feitianmouse 2007-10-29
  • 打赏
  • 举报
回复
mark
xlbdan 2007-10-28
  • 打赏
  • 举报
回复
3楼和4楼的方法都可以完成楼主的要求了

3楼是传统的虚函数做法

4楼是用非虚函数接口来做的

看楼主想要哪个了
ckt 2007-10-28
  • 打赏
  • 举报
回复
像wanfustudio 说的

设计个虚函数,在子类中再去写你像实现的
如果是都是相同的操作,就在子类中添加一个非虚函数,
统一调用接口处理

thecorr 2007-10-28
  • 打赏
  • 举报
回复
龙女的 和工作室的想法都很好。

偶只有赞叹的份了
ilovevvv 2007-10-28
  • 打赏
  • 举报
回复
看不太明白lz需要什么..
要在processMsg里面统一处理m_nProdId??

class CMessage
{
public:
void ProcessProdID()
{
ProcessProdID_Helper();
}
int m_nMessageId;
protected:
virtual void ProcessProdID_Helper() = 0;

};

class CAuthMsg : public CMessage
{
public:
int m_nProdId;
private:
virtual void ProcessProdID_Helper()
{
printf("CAuthMsg Proecess m_nProdId\n");
}
};

class CTrafficAccoutMsg : public CMessage
{
public:
int m_nProdId;
private:
virtual void ProcessProdID_Helper()
{
printf("CTrafficAccoutMsg Proecess m_nProdId\n");
}
};

class CProcessMsg
{
public:
void processMsg(CMessage *pMsg)
{
// 通用处理m_ProdId????
pMsg->ProcessProdID();
}
};
飞哥 2007-10-28
  • 打赏
  • 举报
回复

#include <iostream>
using namespace std;

class CMessage
{
public:
int m_nMessageId;
virtual void processMsg() = 0;
};

class CAuthMsg : public CMessage
{
public:
int m_nProdId;
void processMsg()
{
cout <<"auth<<"<<endl;
}
};

class CTrafficAccoutMsg : public CMessage
{
public:
int m_nProdId;
void processMsg()
{
cout <<"traffic<<"<<endl;
}
};

class CProcessMsg
{
public:
void processMsg(CMessage *pMsg)
{
pMsg->processMsg();
}
};


int main(int argc ,char*argv[])
{
CTrafficAccoutMsg tm;
CAuthMsg am;
CProcessMsg cpm;
cpm.processMsg(&tm);
cpm.processMsg(&am);

return 0;
}

飞哥 2007-10-28
  • 打赏
  • 举报
回复
这个多态不行吗?
独孤过儿 2007-10-28
  • 打赏
  • 举报
回复
可以用 typeid 来实现:


if ( typeid(tmp) == typeid(CTrafficAccoutMsg) )
{
//received a CTrafficAccoutMsg object;
}
else
{
//not a CTrafficAccoutMsg object, is a CAuthMsg object;
}
nevergone 2007-10-28
  • 打赏
  • 举报
回复
我这看类问题最好的解法是:
1.用虚函数,也就是wanfustudio 的方法.
用一个ID来表示处理,不好扩展,代码维护起来很麻烦.这也是很多C++大师告诫我们不用要这样的方法
2.用ilovevvv的方法,ATL/WTL就是采用这种方法来避免虚函数开销
ilovevvv 2007-10-28
  • 打赏
  • 举报
回复
lz的要求好奇怪...
既然数据和处理都一样,直接放在基类不就好了吗=.=
再贴一段,看看是不是能满足你的要求(这样做迟早会出事情的,好的技巧远远比不上好的设计,何况这个技巧还和好不搭边)

class IMessage
{
public:
virtual void ProcessProdID() = 0;
};

template<typename T>
class CMessage : public IMessage
{
public:
void ProcessProdID()
{
T *pT = static_cast<T*>(this);
pT->m_nProdId = 8;
}
int m_nMessageId;
};

class CAuthMsg : public CMessage<CAuthMsg>
{
public:
int m_nProdId;
};

class CTrafficAccoutMsg : public CMessage<CTrafficAccoutMsg>
{
public:
int m_nProdId;
};

class CProcessMsg
{
public:
void processMsg(IMessage *pMsg)
{
// ....lz自己想干嘛干嘛
// 通用处理m_ProdId????
pMsg->ProcessProdID();
}
};

void main()
{
CTrafficAccoutMsg tm;
CAuthMsg am;
CProcessMsg cpm;
cpm.processMsg(&tm);
cpm.processMsg(&am);
}
Faitle 2007-10-28
  • 打赏
  • 举报
回复
呵,可以用dynamic_cast<Derived>判断
如果转型不成功会返回NULL的
yaoike 2007-10-28
  • 打赏
  • 举报
回复

To fetag, Chiyer: 非常感谢,很抱歉我还是没能完整表达我的意思,嗯,对了,我可以看懂你上面在11楼所写的代码。我原来上面的函数写少了一句,麻烦请再看以下的这个方法:

void CProcessMsg::processMsg(CMessage *pMessage)
{
switch (pMessage- >m_nMessageId)
{
case ID_Auth:
CAuthMsg *pMsg = new CAuthMsg;
pMsg = (CAuthMsg*)pMessage;
... // 这里对CAuthMsg对象指针pMsg的数据成员m_nProdId 进行一系列的处理. 例如这句:pMsg- >m_nProdId = 8;
break;
case ID_TrafficAccout:
CTrafficAccoutMsg *pMsg = new CTrafficAccoutMsg;
pMsg = (CTrafficAccoutMsg*)pMessage
... // 这里对CTrafficAccoutMsg 对象指针pMsg的数据成员m_nProdId 也进行一系列的处理.例如都是这句:
// pMsg- >m_nProdId = 8;因为处理与上面的处理相同,我希望把这一块单独提取出来,请问我该如何做?
break;
default:
break;
}
// 如果把 pMsg- >m_nProdId = 8;这句放在这里的话,就跳出了 pMsg指针的作用域,我在这个问题上想了一两天,
// 都想不出一个头绪来,各位可以指点一下吗?注:因为类已经封装好,所以,暂时不考虑把 m_nProdId 放到
// 类CMessage中。请在保持现有类结构的情况下,把这个方法的实现改写一下可以吗?至于这个方法processMsg()
// 的形参个数,返回值等都可以自由定义。非常感谢!!!
//
}





yaoike 2007-10-28
  • 打赏
  • 举报
回复
谢谢大家这么关注这个问题,非常感谢!!!

To sookzeng : 多谢解答,你说的: “但对于lz后来说到的所有派生类共用的代码,建议以常规函数写在基类中,再在派生类的虚函数中调用吧 :)” 我也希望这样做,可是,现在的情况是: 派生类都共有一个数据成员: m_nProdId, 可是,这个共有的数据成员m_nProdId 不可以放在基类 CMessage 里面,我以常规函数写在基类里面,却无法对它的派生类的数据成员 m_nProdId 进行操作处理。 但是,如果我像 wanfustudio,ilovevvv 兄那样分别在派生类里面写虚函数的话,处理却都是相同的,没有做到通用性,请问,像这种情况大家还有没有其它的处理办法呢?
dy_david 2007-10-28
  • 打赏
  • 举报
回复
雁南飞工作室
正解
CQZE 2007-10-28
  • 打赏
  • 举报
回复
Visitor吧

CProcessMsg的动作放在CMessage里面不科学吧。
sookzeng 2007-10-28
  • 打赏
  • 举报
回复
传统的虚函数在什么情况下用比较合适一点,而非虚函数接口又比较适合于用在什么地方呢?
=======================

虚函数用于符合虚函数应用场景的场合 :), 否则,为了提高函数调用效率,不要用虚函数。

至于场景?简单的说,比如当要求写一个函数,它只需接受一个通用参数(基类指针或引用),并可以针对不同的传入类型作不同的处理,而且处理代码只有一句,而不用像lz那样费力的switch。这唯一一句代码写成虚函数的调用即可。

但对于lz后来说到的所有派生类共用的代码,建议以常规函数写在基类中,再在派生类的虚函数中调用吧 :)
xlbdan 2007-10-28
  • 打赏
  • 举报
回复
非常感谢你的再次说明,我对这两种实现的优点和缺点不太了解,传统的虚函数在什么情况下用比较合适一点,而非虚函数接口又比较适合于用在什么地方呢?谢谢~~~


其实这两种实现方法的本质都是一样的,只不过后者把前者用一个非虚函数来封装了一下,一般情况下两者都是可以通用的
sookzeng 2007-10-28
  • 打赏
  • 举报
回复
注:因为类已经封装好,所以,暂时不考虑把 m_nProdId 放到 类CMessage中。请
在保持现有类结构的情况下,把这个方法的实现改写一下可以吗?

---------------------------------------------
lz要求是只能改函数实现啊!那只有把那些相同的代码放到一个独立的函数中处理咯,把要改的参数都传进去(怪怪的:))。

不过还是建议楼主把这种共有的成员抽取到基类中,以基类的统一方法修改。

如果需要在不同派生类中作不同处理,则采用楼上的虚函数的建议吧 :)
星羽 2007-10-28
  • 打赏
  • 举报
回复

void CProcessMsg::processMsg(CMessage *pMessage)
{
CMessage* pMessage = 0;
switch (pMessage- >m_nMessageId)
{
case ID_Auth:
CAuthMsg *pMsg = new CAuthMsg;
pMessage = pMsg;
break;
case ID_TrafficAccout:
CTrafficAccoutMsg *pMsg = new CTrafficAccoutMsg;
pMessage = pMsg;
break;
default:
break;
}


pMessage->m_nProdId = 8;
}

加载更多回复(5)

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧