Halona
Halona

Reputation: 1485

Casting base class to derived through std iterator in C++

in my program I have base GeneralHeader, MacHeader that derived from GeneralHeader and NetworkPacket with member Headers that is std list of 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();
};

While implementing the PrintMe() of Packet_t, that supposed to print all Headers according to HeaderType: if there is a GeneralHeader - it will use GeneralHeader.PrintMe() and if it is MACHeader in the list - it will print MACHeader.PrintMe()) I'm struggling to cast it_Header iterator from base GeneralHeader to derived MACHeader inside Packet_t method PrintMe():

//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++;
    };
};

The error: invalid static_cast from type 'std::_List_iterator' to type 'MACHeader*'

Thank you for any help.

Upvotes: 1

Views: 1623

Answers (2)

user2672165
user2672165

Reputation: 3049

The desired/normal polymorphic way would be: Redefine PrintMe() to a virtual function so that cast is not necessary:

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();
};

Also use vector of pointers to GeneralHeader:

list<GeneralHeader*>::iterator it_Header;

Then you can:

(*it_Header)->printMe();

The for loop will be simpler:

  for (it_Header = Headers.begin(); it_Header != Headers.end();++it_Header)
       (*it_Header)->PrintMe();

I don't know why you need the it_Header to be a member of the class? Can't it just be local to the loop?

Upvotes: 2

piwi
piwi

Reputation: 5336

You need to dereference it_Header to access the "underlying" object to address the compiler error :

static_cast<HW_MACHeader*>(*it_Header)->PrintMe();

Hoever, that will not solve your problem: you have a list of GeneralHeader; therefore because you want to downcast to an instance of HW_MACHeader, you need to use dynamic_cast; this has to be done either on a reference or a pointer:

dynamic_cast<HW_MACHeader&>(*it_Header).PrintMe();

The line above takes the object "referenced" by it_Header, and tells the compiler to cast it dynamically to a reference of type HW_MACHeader.

Note that dynamic_cast will return a null pointer if it cannot cast down to the type you want.

However, this is not a proper way to do this. You should follow user2672165's advice, and use virtual functions.

Upvotes: 1

Related Questions