类的抽象成员应该是指针还是引用
Should abstract members of a class be pointers or references?
类的抽象成员应该是指针还是引用?
举个玩具的例子,假设我有以下类:
class SerializedFileProcessor {
public:
std::string Process(std::string file) const {
std::string text = deserializer.Deserialize(file);
text = processor.Process(text);
return serializer.Serialize(text);
}
private:
IDeserializer? deserializer;
IProcessor? processor;
ISerializer? serializer;
};
其中(具体子类的实例)反序列化程序、处理器和序列化程序都传递到该类的构造函数中。
SerializedFileProcessor不拥有这些,不应删除它们。
这些类成员应该是指针还是引用?或者这种模式应该完全不同吗?
这几乎是依赖注入(/inversation)的hello-world示例。
这里有一个类似的问题,有不同的解决方案:在没有原始指针的C++11中进行依赖注入
编辑:我把原来的答案从这里移到了那个问题上。
SerializedFileProcessor
示例的原始答案:
只使用指针(智能或原始),甚至是普通C++引用的缺点是,它们允许从const上下文调用非常量方法。
我提出了一个类似但不完全相同的包装器std::reference_wrapper
(它缺少const-safe访问器)。将T*
替换为unique_ptr
或shared_ptr
以获得拥有的版本(还添加默认的移动构造)。
template<typename T>
struct NonOwningRef{
NonOwningRef() = delete;
NonOwningRef(T& other) noexcept : ptr(std::addressof(other)) { };
NonOwningRef(const NonOwningRef& other) noexcept = default;
const T& value() const noexcept{ return *ptr; };
T& value() noexcept{ return *ptr; };
private:
T* ptr;
};
用法:
class SerializedFileProcessor {
public:
std::string Process(std::string file) const {
std::string text = deserializer.value().Deserialize(file);
text = processor.value().Process(text);
return serializer.value().Serialize(text);
}
private:
NonOwningRef<IDeserializer> deserializer;
NonOwningRef<IProcessor> processor;
NonOwningRef<ISerializer> serializer;
};
它们可以是任意一种,您必须只确保引用的对象在使用前不会消亡(即,通常其生存期应超过SerializedFileProcessor生存期)。
引用成员有一个缺点,那就是几乎不可能创建赋值运算符(所以如果你需要一个,那么你就需要一个指针——即使对于有引用成员的类,也有一些技术可以进行赋值,但它们非常糟糕)。此外,如果它们是可选的,那么它们需要是指针(引用不是可选的)。
如果您的类不拥有它们,那么它就不应该是引用。使用指针并让所有者持有std::unique_ptr
。
相关文章:
- 如何使用基类指针引用派生类成员
- 将常量指针引用绑定到非常量指针
- 如果非动态变量被指针引用,何时超出范围?
- 转换指针引用的字符串
- 指针引用的生存期(以 C++为单位)
- 从 unique_ptr::get 发送指针作为指针引用进入函数
- 指针/引用的 CLion 格式
- 使用模板专用化来比较指针引用
- 如何保存指向抽象基类的指针/引用,但在 c++ 中仍然可以复制
- C++初始化指针/引用/复制细微差别
- 用数组或指针引用函数?
- 指针范围问题和返回类中封装的指针向量内的指针引用
- 强制转换为指针引用是否会导致未定义的行为
- 访问由 void 指针引用的结构的成员
- C 为什么当先前的步骤引发异常时,std :: shared_ptr的指针引用会被破坏
- 动态指针引用数组由三元运算符返回值,但有异常
- 悬空指向 int 和 char* 常量的指针/引用
- C++ 二维数组和指针引用
- 通过使用指针/引用,在C++中使用向量加快计算速度
- C++非类型模板模板到函数指针/引用