Here's how I handled the problem. User code looks like this:
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);
}
This way every dependency is visible in the user code. The dependencies between objects are nicely stored inside a std::vectors in a Env class. Indexes to the vectors will be returned from the functions. create_A() and use_A() can communicate via ints. The objects will all be destroyed at the same time when Env class goes out of the scope. Your objects could be deriving from a base class which has virtual destructor.
If you have more than one int, recommended way is this:
struct ID { int i; };
Implementation of the interface would rely on the following functions:
A *find_a(const Env &e, ID i);
ID create_a(Env &e, A *ptr);
The above approach solves the following problems with object lifetimes:
- lifetime of the objects
- dependencies between the objects (via ints)
- identifying the objects
- the dependencies could be stored either via int's or via pointers
- destroying the objects when lifetime ends