4

我有两个实现的类:

class DCCmd :
    public DCMessage

class DCReply :
    public DCMessage

两者都是双向发送和接收的协议消息。

现在在协议实现中,我需要创建一个消息队列,但由于DCMessage是抽象的,它不会让我做这样的事情:

class DCMsgQueue{
private:
    vector<DCMessage> queue;
public:
    DCMsgQueue(void);
    ~DCMsgQueue(void);

    bool isEmpty();
    void add(DCMessage &msg);
    bool deleteById(unsigned short seqNum);
    bool getById(unsigned short seqNum, DCMessage &msg);
};

问题在于,正如编译器所说,“DCMessage 无法实例化”,因为它有一个纯抽象方法:

virtual BYTE *getParams()=0;

删除=0并放入空花括号DCMessage.cpp可以解决问题,但这只是一个技巧。

另一个解决方案是我应该制作两个 DCMsgQueues:DCCmdQueueDCReplyQueue,但这只是重复的代码,用于一些琐碎的事情。有任何想法吗?=)

4

5 回答 5

14

您无法实例化该对象,因为正如您所说,它是抽象的。但是,您可以保存一个指向 DCMessage 类的指针向量,该类将起作用,您只需要在将其推送到列表时添加内存地址而不是对象。

vector<DCMessage*> queue;

DCCmd* commandObject = new DCCmd(...params...);
queue.push_back(commandObject);

BYTE* params = queue[0]->getParams();
于 2009-09-14T14:55:06.613 回答
10

你想要一个 DCMessage 指针向量:

vector<DCMessage*> messages;
messages.push_back(new DCCmd(blah));

C++ 中的多态性仅通过指针和引用起作用,您不能为此使用引用。所以,指针它是。

于 2009-09-14T14:56:09.390 回答
3

(对 Kelix 投了赞成票,但我认为这需要更多详细说明)

您要做的是创建一个元素向量,该向量可以是从您的抽象类派生的任何对象,对吗?当您说 时vector <DCMessage>,您是在询问 DCMessage 类元素的向量。你不能拥有它们,因为那是一个抽象类。

如果您改为要求vector <DCMessage *>,那么您可以提供指向从 DCMessage 派生的任何类的对象的指针,并且在运行时调用时将动态(运行时)调度到抽象例程的正确实现。

于 2009-09-14T15:09:25.253 回答
2

如果您想要多态性,则需要 C++ 中的指针,因此将使用指向抽象类型的指针的双端队列(假设它是 FIFO 队列而不是 LIFO )。然后,您将面临管理队列中消息的所有者的问题。

然而,C++ 不仅仅是面向对象的,C++ 中也有将对象写入流的习惯用法。如果消息队列只是将它们转发到 tcp 端口或具有类似于 的行为,您可能希望使用这些惯用语并复制数据,而不是存储对对象的引用。如果您正在实施将消息对象编组到二进制文件或从二进制文件编组的技术,那么如果您的队列只是一个缓冲流,您最终可能会为自己省去一些麻烦。

于 2009-09-14T15:04:40.470 回答
0

其他答案指出您只能拥有抽象类的指针。当您在像列表这样的容器中使用它时,在删除元素后,您还必须手动删除它们的内存,因为容器操作只会对指针值本身起作用,而不是对指向的内容起作用。

在 cpp-11 中,您可以使用包装器unique_ptr<some_type>来实现您的目标,而无需直接处理指针:

list<unique_ptr<your_abstract_class>> someList;

someList.push_back(make_unique<your_derived_class>()); // will create new instance
someList.push_back(make_unique<your_other_derived_class>());

someList.pop_front(); // will remove the instance and automatically call its destructor

于 2020-07-07T10:41:49.973 回答