是否声明抽象类型的字段?首选指针或引用



我有一个抽象类,看起来有点像

class Protocol
{
public:
    // format the string to json or xml depending on impl
    virtual std::string& format(Message& msg) = 0;
    // parse the message from json or xml depending on impl
    virtual Message& parse(std::string& str) = 0;
}

用于从std::string 格式化解析structure Message

struct Message
{
    unsigned long id;
    unsigned char command;
    unsigned int value;
    /* some more fields */
}

现在我有了另一个类",它通过具有该类型的成员来依赖于该类。当然,预计该成员属于Calculator 的亚型

// client.h
class Client
{
public:
    Client(Protocol& protocol);
    /* some methods, e.g. */
    void request(unsigned int amout);
private:
    /* this is what the question below refers to */
    Protocol* pProtocol;   // will compile
    Protocol  cProtocol;   // won't compile (see below)
    Protocol& rProtocol;   // what does this mean?
}
// client.cpp
Client::Client(Protocol& protocol) :  
    // depending on the member
    pProtocol(&protocol) // or
    cProtocol(protocol)  // or
    rProtocol(protocol)
{
}
void Client::request(unsigned int amount)
{
    Message msg;
    msg.id = 1234;
    msg.command = 100;
    msg.value = amount;
    std::string str = 
    // depending on the member
                      pProtocol->format(msg);  // or
                      cProtocol.format(msg);   // or
                      rProtocol.format(msg);
    // some more code to send the string to the server
}

以下是我的问题:

  • 我知道我应该更喜欢像cProtocol这样的类类型的成员,因为像pProtocol这样的指针可能是NULL

  • 不幸的是,这不会与消息一起编译

    cannot declare field 'Client::cProtocol' to be of abstract type 'Protocol'
    

    这是我理解的,因为抽象类Protocol不能被实例化。

  • 那么我应该更喜欢什么?引用成员还是指针成员

  • 这三个选项之间有什么区别特别是在cProtocolrProtocol之间(除了.->以及指针可能是NULL这一事实)

  • 如果我不在构造函数中初始化rProtocol怎么办这会编译吗?它会包含什么?因为它不能用默认值实例化!?

我知道我应该更喜欢像cProtocol这样的类类型的成员,因为像pProtocol这样的指针可能是NULL

一般来说,您更喜欢对象而不是指针,因为该语言通过对对象调用析构函数来帮助您管理资源。但是,使用智能指针(如std::shared_ptr<T>std::unique_ptr<T>)也可以达到同样的效果。

不幸的是,这不会编译为消息"cannot declared field Client::cProtocol to be abstract type Protocol",我理解这一点,因为抽象类Protocol无法实例化。

这不是正确的理由:这样做是因为对象切片,因为不允许将对象切片为抽象类型。

那么我应该更喜欢什么呢?引用成员还是指针成员?

为了使用参考,需要三个条件:

  • 引用的对象必须在构造函数中可用
  • 被引用对象的存在是强制性的(因为不能设置对NULL的引用),并且
  • 您不需要将引用的对象重新指向其他对象,也不需要稍后"清除"引用

如果满足这三个条件,可以使用参考。这告诉代码的读者,由于上面的三个条件,类实例与引用实例具有强边界。

这三个选项之间有什么区别?特别是在cProtocolandrProtocol之间(除了.->以及指针可能是NULL的事实)

cProtocoland制作一个副本(如果它不是抽象的,它会),并剥离所有派生的功能。rProtocol使用一些其他对象,并保持其多态性。pProtocol在何时分配或重新分配以及分配NULLs方面为您提供了更大的灵活性。作为交换,您需要NULL-检查指针,并可以选择在复制构造函数、分配运算符等中管理与其相关的资源。

如果我不在构造函数中初始化rProtocol怎么办?这会编译吗?它会包含什么?因为它不能用默认值实例化!?

如果不能在构造函数中初始化引用,则根本不能对该成员使用引用:指针成为您唯一的选择。

最新更新