类的抽象成员应该是指针还是引用?
对于玩具示例,请说我有以下课程:
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不拥有这些,不应删除它们。
这些类成员应该是指针还是引用?或者这种模式应该完全不同吗?
答案 0 :(得分:1)
这几乎是依赖注入(/ inversion)的hello-world示例。
这里有一个类似的问题,有不同的解决方案:Dependency injection in C++11 without raw pointers
修改:我将原来的答案从这里移到了那个问题。
SerializedFileProcessor
示例的原始答案:
仅使用指针(智能或原始)或甚至是普通的C ++引用的缺点是它们允许从const上下文中调用非const方法。
我提出了一个与std::reference_wrapper
类似但不完全相同的包装器(缺少const安全访问器)。将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;
};
答案 1 :(得分:0)
它们可以是,您必须只确保引用的对象在使用之前不会死亡(即通常它的生命周期应该超过SerializedFileProcessor生命周期)。
引用成员有一个缺点 - 实际上创建赋值运算符几乎是不可能的(所以如果你需要一个,那么你需要一个指针 - 即使对于具有引用成员的类,也有一些实际具有赋值的技术,但它们非常讨厌)。如果它们是可选的,那么它们需要是指针(引用不是可选的)。
答案 2 :(得分:-3)
如果您的班级不拥有它们,则不应该作为参考。使用指针并让所有者持有std::unique_ptr
。