一个具体的问题:
我有一个主应用程序,它具有 A 类型和 B 类型(以及其他类型)的对象。B类型的对象需要正确构造A对象(因此有一个构造函数A(const B&b)。但是Main可能随时更改它持有的B对象。我如何确保当Main更改其B对象时一个对象的内部引用被改变了?
一般来说,在对象具有依赖关系的情况下,管理对象生命周期的一些好的做法是什么?
一个具体的问题:
我有一个主应用程序,它具有 A 类型和 B 类型(以及其他类型)的对象。B类型的对象需要正确构造A对象(因此有一个构造函数A(const B&b)。但是Main可能随时更改它持有的B对象。我如何确保当Main更改其B对象时一个对象的内部引用被改变了?
一般来说,在对象具有依赖关系的情况下,管理对象生命周期的一些好的做法是什么?
如果A
从不缓存任何B
属性,并且始终引用B
它持有的实例以生成任何依赖输出,则对 所做的任何更改B
都应反映在对A
. 我假设您只是B
在构造函数中存储对的引用,而不是创建本地副本。
如果我理解正确,您不仅要更改 B 对象,还要用不同的 B 完全替换它。引用一旦创建就不能更改,因此您需要改用指针。
您可能希望使用观察者模式让 A 对象知道何时应该替换它们的 B:http ://en.wikipedia.org/wiki/Observer_pattern
如果我理解正确,如果您对 main 持有的对象进行修改,它应该反过来影响A
持有的对象。为此,您可以借助构造函数初始化程序。
#include <iostream>
class B{
public:
int num ;
B(int arg):num(arg) {}
};
class A{
public:
const B& ref ;
A( const B& arg ): ref(arg){}
};
int main()
{
B objOne(10) ;
A objTwo(objOne) ;
std::cout << objTwo.ref.num << std::endl ;
objOne.num = 20 ;
std::cout << objTwo.ref.num << std::endl ;
}
输出 :
10
20
记住:
在您的情况下,如果B
实例可以随时来去(旧实例被删除,新实例被“新建”),那么您可以创建一个“包装”B
实例的“实用程序句柄”类:
class BHandle {
B* b_; // can change at any time
public:
....
};
然后,您的A
类将引用一个BHandle
实例,或完全包含一个BHandle
实例。然后,B
实例可以来来去去,但A::my_b_handle_
总是会反映“当前”B
实例的位置。
另一方面,如果B
实例仅具有更改的数据成员(它的实例本身不会来来去去),那么您不需要做任何事情(A
将始终引用同一个B
实例,并且在某些情况下您可能会只需要“通知”它引用A
的对象中的属性发生了变化)。B
一般来说:始终确保您了解所有权。每当您创建一个对象时,另一个对象必须是所有者,或者它必须是局部变量。在您的情况下,主例程将是 B 实例的所有者。如果您在 A 实例中有对 B 的引用,A 将看到对实例的所有更改 - 只要确保您不复制(没有引用确实隐式复制)。所以在你的代码中你会有类似的东西
private:
const B& theReference;
或者
private:
B& theReference;
如果您需要调用非常量方法(请记住在这种情况下还要更改您的构造函数)。
这是我处理问题的方法。用户代码如下所示:
class Env
{
public:
Env();
~Env();
private:
void *priv;
};
class MyInterface
{
public:
MyInterface(Env &e) : e(e) { }
int create_A();
void use_A(int a);
private:
Env &e;
void *priv;
};
int main()
{
Env e;
MyInterface i(e);
int a = i.create_A();
use_A(a);
}
这样每个依赖项在用户代码中都是可见的。对象之间的依赖关系很好地存储在 Env 类的 std::vectors 中。向量的索引将从函数返回。create_A() 和 use_A() 可以通过整数进行通信。当 Env 类超出范围时,所有对象将同时销毁。您的对象可能来自具有虚拟析构函数的基类。
如果您有多个 int,推荐的方法是:
struct ID { int i; };
接口的实现将依赖于以下功能:
A *find_a(const Env &e, ID i);
ID create_a(Env &e, A *ptr);
上述方法解决了对象生命周期的以下问题: