我有一个抽象类,看起来有点像
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
不能被实例化。那么我应该更喜欢什么?引用成员还是指针成员
这三个选项之间有什么区别特别是在
cProtocol
和rProtocol
之间(除了.
与->
以及指针可能是NULL
这一事实)如果我不在构造函数中初始化
rProtocol
怎么办这会编译吗?它会包含什么?因为它不能用默认值实例化!?
我知道我应该更喜欢像
cProtocol
这样的类类型的成员,因为像pProtocol
这样的指针可能是NULL
一般来说,您更喜欢对象而不是指针,因为该语言通过对对象调用析构函数来帮助您管理资源。但是,使用智能指针(如std::shared_ptr<T>
或std::unique_ptr<T>
)也可以达到同样的效果。
不幸的是,这不会编译为消息"cannot declared field
Client::cProtocol
to be abstract typeProtocol
",我理解这一点,因为抽象类Protocol无法实例化。
这不是正确的理由:这样做是因为对象切片,因为不允许将对象切片为抽象类型。
那么我应该更喜欢什么呢?引用成员还是指针成员?
为了使用参考,需要三个条件:
- 引用的对象必须在构造函数中可用
- 被引用对象的存在是强制性的(因为不能设置对
NULL
的引用),并且 - 您不需要将引用的对象重新指向其他对象,也不需要稍后"清除"引用
如果满足这三个条件,可以使用参考。这告诉代码的读者,由于上面的三个条件,类实例与引用实例具有强边界。
这三个选项之间有什么区别?特别是在
cProtocoland
和rProtocol
之间(除了.
与->
以及指针可能是NULL
的事实)
cProtocoland
制作一个副本(如果它不是抽象的,它会),并剥离所有派生的功能。rProtocol
使用一些其他对象,并保持其多态性。pProtocol
在何时分配或重新分配以及分配NULL
s方面为您提供了更大的灵活性。作为交换,您需要NULL
-检查指针,并可以选择在复制构造函数、分配运算符等中管理与其相关的资源。
如果我不在构造函数中初始化
rProtocol
怎么办?这会编译吗?它会包含什么?因为它不能用默认值实例化!?
如果不能在构造函数中初始化引用,则根本不能对该成员使用引用:指针成为您唯一的选择。