c++ - 在作为指针注入到类后重新创建堆栈对象是否不好?
问题描述
// Example program
#include <iostream>
class Foo{
public:
Foo(int a):a(a){}
void print(){
printf("%d\n",a);
}
private:
int a;
};
class Bar{
public:
Bar(Foo* foo):foo(foo){}
void print(){
foo->print();
}
private:
Foo* foo;
};
int main()
{
Foo f = {10};
Bar b(&f);
b.print();
f = {20};
b.print();
}
在上面的代码中,与 Bar 对象共享的 Foo 对象可以在 Bar 不知道的情况下重新创建。想象一下,我必须将 bar 对象注入到第三个类中。现在我可以更新 foo 依赖项,而无需创建新的 bar 对象和第三个类。
这种模式是否普遍使用,是否违反了一些 OOP 原则?
解决方案
我不认为代码做你认为它做的事情。我已经将默认构造函数和分配/运算符添加到您的 Foo 类中,并使用一些日志记录来查看会发生什么。除非您明确禁用它们,否则编译器会自动添加这些构造函数。请参阅此处的输出。
发生了什么
f = {20};
是您构造了一个不同的 Foo 对象,然后将其移动分配给原始实例。
在这种情况下,它相当于
f.a = 20; // Assuming we make a public.
综上所述。如果您的用途只是更改现有实例中的字段(在这种情况下通过分配运算符)。然后一切都应该正常工作。这不一定会使 OOP 原则无效,除非您假设 Bar.foo 是恒定的或不变的。这通常称为组合,并且相当普遍(您的 UI 将包含可能从其他来源修改的各种按钮实例)。
如果您希望更改实现(例如 Foo 是一个虚拟类并且您希望替换不同的派生),那么在您的代码中您将需要有Foo* f = new Foo(10);
. 您将拥有指针的副本,b
并且分配将创建一个新类,该类不会更新b
(类似于f = new FooDerived(20);
.
要使其工作,您需要一个 Provider 类(这是一种 OOP 模式)。这将给你一个Foo
. 最简单的是Foo**
. 但最好有一些更可定制的东西。
也就是说,对于任何严肃的工作都尽量远离裸指针 ( Foo*
)。酌情使用unique_ptr或shared_ptr,免得日后很多麻烦。
推荐阅读
- laravel - 我应该复制控制器,还是使用 artisan:make 控制器?
- python - ns3,Python3 没有名为“ns”的模块
- scala - 为什么使用 SBT 编译时会出现此错误?
- javascript - RegExp 转义函数的问题 - Javascript
- hadoop - Hadoop YARN 资源管理器由于错误而无法启动
- python - 从python列表中的一组点打印x坐标
- javascript - Javascript - 动态推送到新数组?
- json - 具有多个深度级别的 Grails json 转换器
- oracle - 在哪些情况下有人会存储 Oracle DB 对象统计信息
- angular - TypeError 中的错误:无法读取未定义的属性“标志”