声明抽象类型的字段?更喜欢指针或参考?

时间:2014-10-08 13:32:19

标签: c++ pointers reference member

我有一个类似于

的抽象类
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;
}

用于格式化从structure Message

解析std::string
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无法实例化。

  • 所以我应该更喜欢什么?引用成员或指针成员?

  • 3个选项之间有什么区别?特别是在cProtocolrProtocol之间(. vs。->除外指针可能是NULL

  • 的事实
  • 如果我没有在构造函数中初始化rProtocol怎么办?这会编译吗?它包含什么?由于无法使用默认值进行实例化!?

1 个答案:

答案 0 :(得分:2)

  

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

通常,您更喜欢对象到指针,因为该语言可以通过调用它们上的析构函数来帮助您管理资源。但是,您可以使用智能指针实现相同的效果,例如std::shared_ptr<T>std::unique_ptr<T>

  

遗憾的是,由于抽象类协议无法实例化,因此无法使用“无法声明字段Client::cProtocol为抽象类型Protocol”的消息进行编译,因为无法实例化抽象类协议。

这不是正确的理由:它是因为object slicing而完成的,因为不允许将对象切割为抽象类型。

  

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

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

  • 引用的对象必须在构造函数
  • 中可用
  • 引用对象的存在是强制性的(因为您无法设置对NULL的引用)和
  • 您不需要将引用的对象重新指向其他对象,也可以稍后“清除”引用。

如果满足这三个条件,您可以使用参考。这告诉读者您的类实例与引用的实例有很强的界限,因为上面有三个条件。

  

3个选项有什么区别?特别是在cProtocoland rProtocol之间(.->除外,以及指针可能为NULL

cProtocoland制作副本(如果它不是抽象的,它会),并切掉所有派生的功能。 rProtocol使用其他一些对象,并使其保持多态。 pProtocol可让您更灵活地分配或重新分配,以及分配NULL。作为交换,您需要NULL - 检查指针,并可选择在复制构造函数,赋值运算符等中管理与其关联的资源。

  

如果我没有在构造函数中初始化rProtocol怎么办?这会编译吗?它包含什么?由于无法使用默认值进行实例化!?

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