class Addict {
// Something I depend on (hence, the Addict name. sorry.)
Dependency * dependency_;
public:
Addict(Dependency * dependency) : dependency_(dependency) {
}
~Addict() {
// Do NOT release dependency_, since it was injected and you don't own it !
}
void some_method() {
dependency_->do_something();
}
// ... whatever ...
};
如果Dependency是一个纯虚类(也称为穷人版接口),那么这段代码可以轻松地注入一个模拟版本的Dependency(使用类似google mock的东西)。
问题在于,我真的看不出这种代码可能会遇到什么麻烦,以及为什么我应该想要使用除了原始指针之外的任何东西!难道不清楚依赖关系来自哪里吗?
此外,我阅读了很多帖子暗示在这种情况下确实应该使用引用,那么这种代码更好吗?
class Addict {
// Something I depend on (hence, the Addict name. sorry.)
const Dependency & dependency_;
public:
Addict(const Dependency & dependency) : dependency_(dependency) {
}
~Addict() {
// Do NOT release dependency_, since it was injected and you don't own it !
}
void some_method() {
dependency_.do_something();
}
// ... whatever ...
};
我得到了其他同等权威的建议反对使用引用作为成员变量:http://billharlan.com/pub/papers/Managing_Cpp_Objects.html 正如您所看到的,我并不确定各种方法的相对优缺点,所以我有点困惑。如果这已经被讨论过了或者只是在给定项目内个人选择和一致性的问题...但任何想法都是受欢迎的。
答案总结
(我不知道这是否符合良好的SO礼仪,但我会添加代码示例,以展示我从答案中收集到的内容...)
从各种回复中,以下是我可能会在我的情况下采取的做法:
- 将依赖项作为引用传递(至少确保NULL不可能)
- 在一般情况下,如果不能进行复制,则明确禁止复制,并将依赖项存储为引用
- 在较罕见的情况下,如果可以进行复制,则将依赖项存储为原始指针
- 让依赖项的创建者(某种工厂)决定堆栈分配或动态分配(在后一种情况下,通过智能指针进行管理)
- 建立一个约定来将依赖项与自己的资源分开
因此,我最终会得到类似于以下内容:
class NonCopyableAddict {
Dependency & dep_dependency_;
// Prevent copying
NonCopyableAddict & operator = (const NonCopyableAddict & other) {}
NonCopyableAddict(const NonCopyableAddict & other) {}
public:
NonCopyableAddict(Dependency & dependency) : dep_dependency_(dep_dependency) {
}
~NonCopyableAddict() {
// No risk to try and delete the reference to dep_dependency_ ;)
}
//...
void do_some_stuff() {
dep_dependency_.some_function();
}
};
而对于可复制的类:
class CopyableAddict {
Dependency * dep_dependency_;
public:
// Prevent copying
CopyableAddict & operator = (const CopyableAddict & other) {
// Do whatever makes sense ... or let the default operator work ?
}
CopyableAddict(const CopyableAddict & other) {
// Do whatever makes sense ...
}
CopyableAddict(Dependency & dependency) : dep_dependency_(&dep_dependency) {
}
~CopyableAddict() {
// You might be tempted to delete the pointer, but its name starts with dep_,
// so by convention you know it is not your job
}
//...
void do_some_stuff() {
dep_dependency_->some_function();
}
};
据我所了解,没有办法表达“我有一些东西的指针,但我不拥有它”的意图,编译器也无法强制执行。因此,我必须在这里采用命名约定...
保存作为参考
正如Martin指出的那样,以下示例并没有解决问题。
或者,假设我有一个拷贝构造函数,可以这样实现:
class Addict {
Dependency dependency_;
public:
Addict(const Dependency & dependency) : dependency_(dependency) {
}
~Addict() {
// Do NOT release dependency_, since it was injected and you don't own it !
}
void some_method() {
dependency_.do_something();
}
// ... whatever ...
};
NonCopyableAddict&operator =(const NonCopyableAddict&other);
- clickMe// 防止复制
** NonCopyableAddict & operator = (const NonCopyableAddict&); NonCopyableAddict(const NonCopyableAddict& ); ** - Andrei Bacescu