实例可复制类
class object
{
public:
object(dependency d) : dep_(d) {}
private:
dependency dep_;
};
仅在 dependency 类完全无状态的情况下有效,即没有任何成员。实际上,这种情况很少发生,因为dependency 类可能会存储自己的依赖项。
原始指针
class object
{
public:
object(dependency *d) : dep_(d)
{
if (d == nullptr)
throw std::exception("null dependency");
}
private:
dependency *dep_;
};
这就像真正的注入一样。我们需要检查传递的指针是否有 nullptr 值。
object 类不拥有dependency 类,因此调用代码有责任确保object 在dependency 对象之前被销毁。
在实际应用中,有时很难验证。
参考
#define DISALLOW_COPY_AND_ASSIGN(Class) \
Class(const Class &) = delete; \
Class &operator=(const Class &) = delete
class object
{
public:
object(dependency &d) : dep_(d) {}
DISALLOW_COPY_AND_ASSIGN(object);
private:
dependency &dep_;
};
引用不能为空,所以在这个预期中会更安全一些。
但是,这种方法给object 类带来了额外的限制:它必须是不可复制的,因为无法复制引用。您必须手动覆盖赋值运算符和复制构造函数以停止复制或从 boost::noncopyable 之类的东西继承它。
与原始指针一样,所有权约束已到位。调用代码应为这两个类提供正确的销毁顺序,否则引用将变为无效并且应用程序因访问冲突而崩溃。
如果依赖是一个常量引用:
class object
{
public:
object(const dependency &d) : dep_(d) {}
private:
const dependency &dep_;
};
您应该注意object 类接受对临时对象的引用:
dependency d;
object o1(d); // this is ok, but...
object o2(dependency()); // ... this is BAD.
更多细节:
智能指针
class object
{
public:
object(std::shared_ptr<dependency> d) : dep_(d)
{
if (!d)
throw std::exception("null dependency");
}
private:
std::shared_ptr<dependency> dep_;
};
类似于原始指针,但所有权由智能指针机制控制。
仍然需要在构造函数体中检查nullptr。
主要优点是dependency 对象生命周期控制:调用应用程序无需正确控制销毁顺序(但请考虑you need to be very careful when designing your APIs with std::shared_ptr)。
一旦dependency 类不再使用,它就会被shared_ptr 析构函数自动销毁。
有些情况下shared_ptr 拥有的对象不会被销毁(所谓的cyclic references)。但是,使用构造函数注入,由于特定的定义良好的构造顺序,循环依赖是不可能的。
如果整个应用程序中没有使用其他注入方法,这当然可以工作。
智能指针的开销很小,但在大多数情况下并不是真正的问题。
更多细节: