现在的位置: 首页 > 综合 > 正文

C++使用模板进行的一种重构

2014年01月05日 ⁄ 综合 ⁄ 共 4901字 ⁄ 字号 评论关闭

如果有一些遗留代码,里面有很多结构,定义了一些相同的成员,但在一些时候,需要取出这些成员,进行同样的处理。如下面这些代码的红色部分。

——原先的程序结构是使用类型码来区分实际的类型,客观地说,这些遗留代码是比较混乱的。

不想说太多,用简单的代码来说明问题吧。

typedef struct   _EVT_SWITCH : public EVT_HEAD {
 DWORD dwCategory;
 DWORD  dwSeverity;
 DWORD dwEvtSrcID;
 DWORD dwEvtSrcOffset;
 DWORD   dwSrcIp;
 DWORD   dwSrcPort;
 DWORD   dwDstIp;
 DWORD   dwDstPort;
 DWORD   dwProtocol;
 DWORD dwEvtUserOffset;
 DWORD   dwEvtUserIp;
 DWORD dwStatus;
 DWORD   dwOp;
 DWORD dwEvtNum;
 DWORD dwDetailOffset;
 CHAR szContent[0];
}EVT_SWITCH,*PEVT_SWITCH;

typedef struct   _EVT_ROUTER : public EVT_HEAD {
 DWORD dwCategory;
 DWORD  dwSeverity;
 DWORD dwEvtSrcID;
 DWORD dwEvtSrcOffset;
 DWORD   dwSrcIp;
 DWORD   dwSrcPort;
 DWORD   dwDstIp;
 DWORD   dwDstPort;
 DWORD   dwProtocol;
 DWORD dwEvtUserOffset;
 DWORD   dwEvtUserIp;
 DWORD dwStatus;
 DWORD   dwOp;
 DWORD dwEvtNum;
 DWORD dwDetailOffset;
 CHAR szContent[0];
}EVT_ROUTER,*PEVT_ROUTER;

typedef struct  _EVT_NETWORK : public EVT_HEAD {
 DWORD dwCategoryOffset;
 DWORD  dwSeverity;
 DWORD dwEvtId;
 DWORD dwEvtSrcOffset;
 DWORD dwEvtUserOffset;
 DWORD dwEvtTypeOffset;
 DWORD dwSrcIp;
 DWORD dwSrcPort;
 DWORD dwDstIp;
 DWORD dwDstPort;
 DWORD dwProtocol;
 DWORD dwSmacOffset;
 DWORD dwDmacOffset;
 DWORD dwFlagOffset;
 DDWORD ddwInB,ddwOutB,ddwInPkt,ddwOutPkt;
 DDWORD ddwSessionId;
 DWORD dwRuleOffset;
 DWORD dwStatusOffset;
 DWORD dwOpOffset;
 DWORD dwReasonOffset;
 int tDuration;
 DWORD dwEvtNum;
 DWORD   dwArgOffset;
 DWORD dwMsgOffset;
 DWORD dwDetailOffset;
 CHAR szContent[0];
}EVT_FW,*PEVT_FW,EVT_NETWORK,*PEVT_NETWORK;

typedef struct  _EVT_VPN : public EVT_HEAD {
 int tDuration;
 DWORD dwCategoryOffset;
 DWORD  dwSeverity;
 DWORD dwEvtId;
 DWORD dwEvtSrcOffset;
 DWORD dwEvtUserOffset;
 DWORD dwEvtTypeOffset;
 DWORD   dwDevActionOffset;
 DWORD dwDevMoudleNameOffset;
 DWORD dwServiceOffset;
 DWORD dwSrcIp;
 DWORD dwSrcPort;
 DWORD dwDstIp;
 DWORD dwDstPort;
 DWORD dwProtocol;
 DWORD dwSmacOffset;
 DWORD dwDmacOffset;
 DWORD dwTargetUserIDOffset;
 DWORD dwTargetDomainOffset;
 DWORD dwMessageIDOffset;
 DWORD dwTunnelOffset;
 DWORD dwInterfaceOffset;
 DWORD   dwMmemonicOffset;
 DWORD dwFlagOffset;
 DDWORD ddwInB,ddwOutB,ddwInPkt,ddwOutPkt;
 DDWORD      ddwSessionId;
 DWORD dwStatusOffset;
 DWORD dwOpOffset;
 DWORD dwReasonOffset;
 DWORD dwEvtNum;
 DWORD   dwArgOffset;
 DWORD dwMsgOffset;
 DWORD dwDetailOffset;
 CHAR szContent[0];

}EVT_VPN,*PEVT_VPN;

typedef struct  _EVT_SECURE : public EVT_HEAD {
 DWORD dwCategoryOffset;
 DWORD dwSeverity;
 DWORD dwEvtTypeOffset;
 DWORD dwEvtSrcOffset;
 DWORD dwEvtUserOffset;
 DWORD dwSrcIp;
 DWORD dwSrcPort;
 DWORD dwDstIp;
 DWORD dwDstPort;
 DWORD dwProtocol;
 DWORD dwFlagOffset;
 DDWORD ddwInB,ddwOutB,ddwInPkt,ddwOutPkt;
 DDWORD ddwSessionId;
 DWORD dwRuleOffset;
 DWORD dwStatusOffset;
 DWORD dwOpOffset;
 DWORD dwReasonOffset;
 DWORD dwEvtId;
 DWORD dwEvtNum;
 DWORD   dwSignatureOffset;
 DWORD dwDetailOffset;
 CHAR    szContent[0];
}EVT_SECURE,*PEVT_SECURE;

这些类型实际上是同一类类型,实际上可以从同一个类派生,使用 PullUp Member 方法重构。但是这些结构已经发布,不可能施行这种重构。可以这样:

class CEventWrapper
{
public:
 CEventWrapper(PEVT_HEAD p) { m_p = p; }

 struct NetInfo
 {
  DWORD dwDstIp;
  DWORD dwDstPort;
  DWORD dwSrcIp;
  DWORD dwSrcPort;
  DWORD dwProtocol;
  TCHAR szDstMac[20];
  TCHAR szSrcMac[20];
 };
 BOOL GetNetInfo(NetInfo* p) const;
 template static void
  TemplateGetNetInfo(CEventWrapper::NetInfo* netInfo, const T& x)
 {
  netInfo->dwDstIp  = x.dwDstIp;
  netInfo->dwDstPort = x.dwDstPort;
  netInfo->dwSrcIp  = x.dwSrcIp;
  netInfo->dwSrcPort = x.dwSrcPort;
  netInfo->dwProtocol = x.dwProtocol;
 }

 BOOL   HasNetInfo() const;

private:
 PEVT_HEAD m_p;
};

BOOL CEventWrapper::HasNetInfo() const
{
 NetInfo ni;
 return GetNetInfo(&ni);
}

BOOL CEventWrapper::GetNetInfo(NetInfo* netInfo) const
{
 memset(netInfo, 0, sizeof(NetInfo));

 switch (m_p->dwLogFrt)
 {
 default:
  ASSERT(0);
  return FALSE;
 case DIAL_LOG:
 case WEBTRENDS_LOG:
 case SNORT_LOG:
 case SENDMAIL_LOG:
 case SYSLOG:
 case NETSCREEN_LOG:
 case WIN_FILE_LOG:
 case WIN_PROCESS_LOG:
 case APACHE_ERROR_LOG:
 case IP_MON_LOG:
 case IP_UP_LOG:
 case PROC_MON_LOG:
 case GENERAL_MON_LOG:
 case PERF_MON_LOG:
 case PORTMON_LOG:
  ASSERT(0);
  return FALSE;

 case EVENT_LOG:   return FALSE;

 case CP_LOG:
  TemplateGetNetInfo(netInfo, *(EVT_VIRUS*)(m_p + 1));
  return TRUE;
 case VPN_LOG:
  TemplateGetNetInfo(netInfo, *(EVT_VPN*)(m_p + 1));
  return TRUE;

 case SECEXPERT_LOG:  return FALSE;

 case IIS_FTP_LOG:  return FALSE;
 case EXCHANGE_LOG:  return FALSE;
 case FW_LOG:
  {
   EVT_FW* p = (EVT_FW*)(m_p + 1);
   TemplateGetNetInfo(netInfo, *p);
   if (p->dwDmacOffset)
    lstrcpyn(netInfo->szDstMac, p->dwDmacOffset + (char*)p,
     dimof(netInfo->szDstMac));
   if (p->dwSmacOffset)
    lstrcpyn(netInfo->szSrcMac, p->dwSmacOffset + (char*)p,
     dimof(netInfo->szSrcMac));
   return TRUE;
  }
 case DOMINO_HTTP_LOG:
 case APACHE_LOG:
 case IIS_HTTP_LOG:
  return FALSE;

 case CISCO_PIX_LOG:
 case CISCO_IOS_LOG:
 case CISCO_SWITCH_LOG:
 case HUAWEI_SWITCH_LOG:
 case NORTEL_SWITCH_LOG:
  TemplateGetNetInfo(netInfo, *(EVT_SWITCH*)(m_p + 1));
  return TRUE;

 case SQLSERVER_LOG:  
 case ORACLE_LOG:
 case MYSQL_LOG:
  return FALSE;

 case KIDS_LOG: case IDS_LOG:
  TemplateGetNetInfo(netInfo, *(EVT_SECURE*)(m_p + 1));
  return TRUE;
 }
 ASSERT(0);
 return FALSE;
}

抱歉!评论已关闭.