c++ - 类成员和依赖注入的对象与引用
问题描述
我是 C++ 新手,具有 C# 背景。我正在尝试在 C++ 中使用 C# 中常用的依赖注入,我对声明依赖项并将它们传递的不同方式以及为什么我会使用其中一种方式感到困惑。让我们假设A
取决于B
。
方法 #1 - 声明为对象并获取对象
class A
{
private:
B _b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
方法 #2 - 声明为对象并引用
class A
{
private:
B _b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
方法 #3 - 声明为引用并获取对象- 从头开始 - 未定义的行为
class A
{
private:
B &_b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
方法#4 - 声明为引用并引用
class A
{
private:
B &_b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
我已经尝试了以上所有方法,它们似乎都有效。它们之间有什么区别吗?如果是这样,我为什么要选择一个而不是另一个?我的偏好是#1,因为我发现它是最熟悉和最直观的。
我在这里找到了类似的讨论讨论,但更多的是关于指针与引用。
解决方案
在这方面,C# 和 C++ 之间的主要区别之一是,在 C# 中类是引用类型,而在 C++ 中它们是值类型。
方法 1 和 2 基于复制构造。如果传递给构造函数的对象恰好是B
. 但是,如果您使用 B 的派生类,它可能会由于对象切片而失败。如果源对象是常量,方法 2 也可能会失败。
方法3:不再考虑(在您的问题中划伤)
方法4:可以,只要通过引用传递的对象继续存在,只要该对象。但是,如果 functionB::Bar()
不是虚函数,则B::Bar()
始终会在 中调用Foo()
,即使您使用从 B 派生的类及其自己的Bar()
.
方法 5:使用智能指针并克隆通过引用传递的对象(使用clone()
成员或使用模板构造函数):
class A
{
private:
unique_ptr<B> _b;
public:
template<class T>A(const T&b): _b(make_unique<T>(b)) { }
void Foo()
{
_b->Bar();
}
};
推荐阅读
- node.js - DynamoDb:如何根据具有最高编号的列获取项目?
- python - 如何创建具有特定 dtype 的新 Pandas 列?
- go - 处理程序提供服务后,如何从请求对象中取回记录器对象?
- rails-activestorage - 如何缩短 Rails Active Storage url 链接太长
- java - 如何遍历列表列表以操作内部列表的内容?
- sql - 如何在 Snowflake 中重命名表的多个列?
- java - Apache Commons CSVParser - 如何将列拆分为单独的键?
- python - 监控估算器进度和 sklearn 包装器
- html - 用 v-html 绑定图片
- java - 如何更改 Apache Tomcat 9 的 Java 版本