通过 C++ 中的 std 迭代器将基类转换为派生
Posted
技术标签:
【中文标题】通过 C++ 中的 std 迭代器将基类转换为派生【英文标题】:Casting base class to derived through std iterator in C++ 【发布时间】:2014-03-11 13:49:50 【问题描述】:在我的程序中,我有从 GeneralHeader 和 NetworkPacket 派生的基本 GeneralHeader、MacHeader,其成员 Headers 是 GeneralHeader 的标准列表:
//Packet.h
enum HeaderType_t General_Header_type, MAC_Header_type;
class GeneralHeader
public:
bool Valid;
HeaderType_t HeaderType;
void PrintMe();
;
struct MACHeader: public GeneralHeader
long unsigned DestAddr:48;
long unsigned SourceAddr:48;
void PrintMe();
;
struct Packet_t
list<GeneralHeader> Headers;//TODO GeneralHeader
list<GeneralHeader>::iterator it_Header; //TODO GeneralHeader
void PrintMe();
;
在实现 Packet_t 的 PrintMe() 时,应该根据 HeaderType 打印所有标头:如果有 GeneralHeader - 它将使用 GeneralHeader.PrintMe() 并且如果它是列表中的 MACHeader - 它将打印 MACHeader。打印我()) 我正在努力将 it_Header 迭代器从基本 GeneralHeader 转换为 Packet_t 方法 PrintMe() 中的派生 MACHeader:
//Packet.cpp
void GeneralHeader::PrintMe()
std::cout << "Valid " << GeneralHeader::Valid << endl;
std::cout << "Header Type " << GeneralHeader::HeaderType << endl;
;
void HW_MACHeader::PrintMe()
std::cout << "------------------------ " << endl;
std::cout << "---- MAC HEADER --- " << endl;
std::cout << "------------------------ " << endl;
GeneralHeader::PrintMe();
;
void NetworkPacket_t::PrintMe()
std::cout << "Valid Packet " << NetworkPacket_t::ValidPacket << endl;
for (it_Header = Headers.begin(); it_Header != Headers.end(); it_Header++)
switch (it_Header->HeaderType)
case MAC_Header_type:
static_cast<HW_MACHeader*>(it_Header)->PrintMe();
break;
default:
std::cout << "default" << endl;
;
it_Header++;
;
;
错误:从类型“std::_List_iterator”到类型“MACHeader*”的静态转换无效
感谢您的帮助。
【问题讨论】:
您没有告诉我们Headers
是什么NetworkPacket_t
,但假设它是list<GeneralHeader>
,为什么不转换迭代值,即static_cast<HM_MacHeader>(*it).PrintMe()
?跨度>
Benjamin,我现在尝试了“static_cast所需的/正常的多态方式是: 将 PrintMe() 重新定义为一个虚函数,这样就不需要强制转换了:
class GeneralHeader
public:
bool Valid;
HeaderType_t HeaderType;
virtual void PrintMe();
;
class MACHeader: public GeneralHeader
long unsigned DestAddr:48;
long unsigned SourceAddr:48;
public:
void PrintMe();
;
也使用指向 GeneralHeader 的指针向量:
list<GeneralHeader*>::iterator it_Header;
那么你可以:
(*it_Header)->printMe();
for 循环会更简单:
for (it_Header = Headers.begin(); it_Header != Headers.end();++it_Header)
(*it_Header)->PrintMe();
我不知道你为什么需要 it_Header 成为班级的成员?它不能只是循环的本地吗?
【讨论】:
您好 user2672165,我已经采纳了您的建议,但现在我在定义 for-loop 时遇到了困难:如何定义 for-loop 的语句 - (it_Header = Headers.begin(); it_Header != Headers.end(); it_Header++) - 当迭代器按照您的建议定义时?谢谢 @Halona:添加了循环。希望对您有所帮助。【参考方案2】:您需要取消引用it_Header
以访问“基础”对象以解决编译器错误:
static_cast<HW_MACHeader*>(*it_Header)->PrintMe();
但是,这并不能解决您的问题:您有一个 GeneralHeader
列表;因此因为要向下转换为HW_MACHeader
的实例,所以需要使用dynamic_cast
;这必须在引用或指针上完成:
dynamic_cast<HW_MACHeader&>(*it_Header).PrintMe();
上面的行采用it_Header
“引用”的对象,并告诉编译器将其动态转换为HW_MACHeader
类型的引用。
请注意,如果dynamic_cast
无法向下转换为您想要的类型,它将返回一个空指针。
但是,这不是执行此操作的正确方法。你应该听从 user2672165 的建议,使用虚函数。
【讨论】:
Piwi,我收到错误:从类型“GeneralHeader”到类型“HW_MACHeader*”的静态转换无效以上是关于通过 C++ 中的 std 迭代器将基类转换为派生的主要内容,如果未能解决你的问题,请参考以下文章