2014-10-08 33 views
1

我有一个抽象类,看起来像声明抽象类型的字段?喜欢指针还是参考?

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

  • 不幸的是这不会对消息

    编译

    我明白了,因为抽象类Protocol不能实例化。

  • 因此我应该选择什么?一个引用成员或一个指针成员?

  • 3个选项之间有什么区别?特别是与rProtocol之间cProtocol(除.->和事实指针可能NULL

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

回答

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 s的更大灵活性。作为交换,您需要NULL - 检查指针,并可选择管理与拷贝构造函数,赋值运算符等关联的资源。

如果我没有在构造函数中初始化rProtocol会怎么样?这会编译?它包含什么?由于它不能用默认值实例化!?

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

+0

感谢您的详细解答。我来自Java,对象切片对我来说是全新的! – ultimate 2014-10-08 14:13:28