在C ++中使用派生类的方法通过指向基类的方法

时间:2014-03-12 09:31:39

标签: c++ iterator

在我的程序中,我有2个标题(IP和MAC标题),这些标题是' sons' GeneralHeader。所有常规,IP和MAC头类都具有PrintMe()函数。另外,我有一个包含GeneralHeaders列表的Packet类(该列表实际上可能有IP或MAC头:(没有IP defenition,缩短):

//Packet.h

    class GeneralHeader {
    public:
        bool Valid;
        HeaderType_t HeaderType; // MAC or IP
        virtual void PrintMe();
    };

    class HW_MACHeader: public GeneralHeader {
    public:
        long unsigned DestAddr:48;
        long unsigned SourceAddr:48;
        virtual void PrintMe();
    };

    struct NetworkPacket_t {
        NetworkPacket_t();
        list<GeneralHeader> Headers;//TODO GeneralHeader
        void PrintMe();
    };

我很难实现PrintMe()方法,该方法将使用适当的MAC或IP PrintMe()方法(而不是GeneralHeader的基础PrintMe())打印GeneralHeaders列表:

//Packet.cpp

//This implementation prints GeneralHeaders :(
//(although MAC headers were added to the Headers list)

void NetworkPacket_t::PrintMe() {
    list<GeneralHeader>::iterator it_H;
    for (it_H = Headers.begin(); it_H != Headers.end(); ++it_H) {
        it_H->PrintMe();
    };
};

另一个尝试是将迭代器it_H强制转换为适当的MAC或IP头(根据HeaderType),但无论我试图如何投射它,它都不起作用,例如:

//Packet.cpp
//Casting implementation
//Here I get run error: 
//terminate called after throwing an instance of 'std::bad_cast'

void NetworkPacket_t::PrintMe() {
    list<GeneralHeader>::iterator it_H;
    for (it_H = Headers.begin(); it_H != Headers.end(); ++it_H) {
        switch (it_H->HeaderType) {
        case General_Header_type:
            std::cout << " General Header " << endl;
            it_H->PrintMe();
            break;
        case MAC_Header_type:
            dynamic_cast<HW_MACHeader&>(*it_H).PrintMe();
            break;
        default:
            std::cout << " default" << endl;
        };
    };
};

我非常感谢你能提供任何帮助

2 个答案:

答案 0 :(得分:1)

原因是您将object而不是pointer存储到了list。它类似于:

HW_MACHeader hw;
GeneralHeader gh = hw;

您将child object分配给parent object,因此示例中的gh实际上是hw的第一部分。你可以阅读object slicing

使用pointer是正确的方法:

HW_MACHeader hw;
GeneralHeader *gh = &hw;

然后当你打电话

gh->PrintMe();

它将调用PrintMe中的HW_MACHeader函数。

看看这个:

#include <iostream>
#include <list>
using namespace std;

class GeneralHeader {
public:
    bool Valid;
    virtual void PrintMe() {cout << "General" << endl;}
};

class HW_MACHeader: public GeneralHeader {
public:
    long unsigned DestAddr;
    long unsigned SourceAddr;
    virtual void PrintMe() {cout << "HW" << endl;}
};

struct NetworkPacket_t {
    NetworkPacket_t(){}
    list<GeneralHeader *> Headers;//TODO GeneralHeader
    virtual void PrintMe();
};

void NetworkPacket_t::PrintMe() {
    list<GeneralHeader *>::iterator it_H;
    for (it_H = Headers.begin(); it_H != Headers.end(); ++it_H) {
        (*it_H)->PrintMe();
    }
}

int main()
{
    NetworkPacket_t t;
    HW_MACHeader t1;
    GeneralHeader t2;
    t.Headers.push_back(&t1);
    t.Headers.push_back(&t2);

    t.PrintMe();
    return 0;
}

所有作业都将替换为pointer而不是object。输出是:

HW
General

答案 1 :(得分:0)

您可以将智能指针存储在容器中,

list<shared_ptr<GeneralHeader>>

然后虚函数将通过指向基类的指针按预期工作。