A concrete problem:
I have a Main application which has objects of type A and type B (among other types).
Object of type B requires A object to be properly constructed (so there is a constructor
A(const B& b). However Main may change B object it holds at any time. How do I make
sure that when Main changes its B object then the A object's internal reference is changed ?
In general, what are some good practices to manage object lifetimes, where objects
have dependencies ?
If A never caches any of B properties, and always references the instance of B it holds to generate any dependent output, any changes that are made to B should be reflected in subsequent calls to A. I am assuming you're simply storing a reference to B within the constructor and not creating a local copy.
If I understand correctly, you want to not just change the B object but completely replace it with a different B. References can't be changed once created, so you'll want to use pointers instead.
You may want to use the Observer Pattern to let the A objects know when their B should be replaced: http://en.wikipedia.org/wiki/Observer_pattern
In general: Always make sure you know about the ownership. Whenever you create an object, wither another object needs to be the owner or it has to be a local variable. In your case the main routine would be the owner of the instance to B. If you have a reference to B in your A instance, A will see all changes to the instance - just make sure you do not copy (not having a reference does implicit copying). So in your code you would have something like
private:
const B& theReference;
or
private:
B& theReference;
if you need to call non-const methods (remember to also change your constructor in that case).
If I understood you correctly, if you make modifications to an object that main holds, it should in turn effect the object what A holds. For this you may take the help of constructor initializer.
#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 ;
}
Output :
10
20
Keep in mind:
All problems can be solved with one more layer of indirection.
Object ownership must be obvious.
In your case, if the B instance can come-and-go at any time (the old instance is deleted, a new one is "newed"), then you can create a "utility handle" class that "wraps" the B instance:
class BHandle {
B* b_; // can change at any time
public:
....
};
Then, your A class would reference a BHandle instance, or wholly contain a BHandle instance. Then, B instances can come-and-go, but A::my_b_handle_ would always reflect where the "current" B instance is.
On the other hand, if the B instance merely has data members that change (its instance itself does not come-and-go), then you don't need to do anything (A will always reference the same B instance, and you may in some cases merely need to "notify" A that properties changed in the B object it references).
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
Related
I'm new to C++, with a C# background. I'm trying to use dependency injection commonly used in C# in C++ and I'm confused about the different ways to declare dependencies and pass them in and why I would use one over the other. Let's assume A depends on B.
Approach #1 - declare as object and take object
class A
{
private:
B _b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #2 - declare as object and take reference
class A
{
private:
B _b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #3 - declare as reference and take object - scratch this - undefined behavior
class A
{
private:
B &_b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #4 - declare as reference and take reference
class A
{
private:
B &_b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
I've tried all of the above and they all seem to work. Is there any difference between them? and if so why should I choose one over the other? my preference is #1 because I find it the most familiar and intuitive.
I've found a similar discussion discussion here but that's more about Pointers vs References.
One of the main difference between C# and C++ in this regard is that in C# classes are reference types whereas in C++ they are value types.
Approach 1 and 2 are based on copy construction. This could work if the object passed to the constructor is exactly a B. But it might fails due to object slicing if you'd use a derived class of B. Approach 2 might also fail if the source object is a constant.
Approach 3: no longer considered (scratched in your question)
Approach 4: is ok, provided the object passed by reference continues to exist as long as the object. However if function B::Bar() is not a virtual function, B::Bar() would always be called in Foo(), even if you'd use a class derived from B with its own implementation of Bar().
Approach 5: use a smart pointer and clone the object passed by reference (either with a clone() member, or by using templated constructor):
class A
{
private:
unique_ptr<B> _b;
public:
template<class T>A(const T&b): _b(make_unique<T>(b)) { }
void Foo()
{
_b->Bar();
}
};
Online demo
In your case I'd say that best solution from all mentioned is taking and storing reference. The whole point of dependency injection is using pure virtual interface without even knowing how something is implemented. It means that underneath you want vtable lookup that will execute whatever implementation is for object that is referenced. This way you can expect reference for Animal where callers will provide Elephant or Cat implementation of Animal. Moreover, if you use pure virtual interface (with at least one pure virtual function inside) you can't even pass object by value because you can't create object of pure virtual type.
As far as I remmember, C# similarly to Java distinguishes objects from builtin types and objects are passed by reference by default. In C/C++ you explicitly pass everything the way you want, so in your cases you have:
Copy of temporary copy of B You make more copies than you need. If your object is big, it will cause performance loss.
Copy of B If you simply want to store copy of some object it seems to be better way but you created not needed limitation here. If you make copy of an object, you won't modify original object. By passing it by non-const reference you create this limitation and you can't take const objects because of that. If you simply want to take some object by reference and store copy of it, most of the time you want const reference. Exceptions might be in case of noncopyable objects.
reference to temporary copy of B (invalid)
Reference to B Is completely different story. Here you don't store copy of an object but point to original one, so every change you make on this object will be visible to anyone else that has access to object you received. That's more or less how objects work by default in languages like Java. Moreover, you can use virtualization as I mentioned before. The only drawback is that you have to ensure that this object exists as long as you are using it - you are not the owner of B. You just use that but someone has control of it's existence.
As you can see, in first case Second case creates some not needed limitation. You create copy of non-const
I am writing a program that contains several classes and I am trying to access class A instance from class B. I am using setA() and getA() for A'a data member and I am using the same for class B. In class B I also have a function that gets the member from A via the getA() function call. I then want to compare if A's member is the same as B's member.
class A {
private:
int a;
public:
void setA(int a);
int getA();
}
class B {
private:
int b;
public:
void setB(int b);
int getB();
bool compareA_B(){
A a.getA(); // <- this is a new object A
B b.getB();
if(a == b)
return true;
else
return false;
}
}
When I call setA() in my main function by A a_in_main.setA(2) this A is a different instance than the one above with the arrow.
My question is how do I access the correct instance of A in the B function compare()?
I kind of think I need to use pointers but I am not sure. I have been looking all over the internet and I can't find anything concrete.
I edited this post and I hope this is more clear.
When declaring int a you are declaring that the class' instance will hold an int, not a reference to one.
When you're setting you also do the same in the function by passing the argument by value (which most likely copies in real world scenarios), so even if it was a pointer internally you could end up with your "reference" referring to a newly made copy.
Your member, and the signature of the functions handling it, need to be pointers or references of some flavor to an int, which will store the memory address it's located at, and when compared will compare memory locations and not the value stored in it.
The syntax for a pointer to a value of some type is type* var.
int* var, int *var, int * var are all equivalent, you will find it expressed all ways depending on the author.
You might also, depending on what the intended use of that member is, want to ensure it can't alter the data it points to const int* var.
It sounds like you're very early on in learning C++, some beginner books or YouTube videos might help. Wrapping referenced values in classes before you know how to make a pointer might be a sign of trying to run before being able to walk.
And again a bad-formulted question, but I don't know how to shortly explain this situation:
I have two classes. Let's name them A and B. A has a lot of member variables and methods. B is a struct which has a shared_pointer to an object of type A. Now A has a method that returns an instance of B (with a pointer to the current instance of A).
My problem is, that A is the subclass of C. C has the same method as described above as pure virtual. The code would look like this:
class C {
public:
virtual B mymethod() const =0;
virtual int getMyvar() const =0;
};
class A : public C {
public:
B mymethod() const override;
int getMyvar() const override; //outputs myvar
private:
int myvar;
};
struct B {
std::shared_ptr<C> pointer;
};
B A::mymethod() const {
B instance;
instance.pointer = std::make_shared<A>(*this); //is this wrong?
return instance;
}
My compiler (gcc 4.8.2) creates the executables for the following code, but at runtime I get "Segmentation fault (core dumped)":
void AnotherClass::something() const {
A object;
B instance = object.mymethod();
std::cout << instance.pointer->getMyvar(); //dumps the core womehow?
}
I read about the std::enable_shared_from_this but I could not figure out how it works or if it helps me.
Why do I get the error message and how can I fix this?
From what I have read in the manual, you do:
class A : public C, std::enable_shared_from_this<A> {
public:
B mymethod() override; // Notice the lack of const
private:
int myvar;
};
and then:
B A::mymethod() {
B instance;
instance.pointer = shared_from_this(); // this should be right
return instance;
}
Like this, all the instances of a std::shared_ptr to the same A object will share the same reference counter, and it will be destroyed only when it must be.
EDIT:
Also, notice that your object A must be managed by some other std::shared_ptr before you can call A::mymethod(). I.e. you must create A objects like this:
std::shared_ptr<A> a_obj(new A);
then you can call A::mymethod():
B b_obj = a_obj->mymethod();
EDIT2:
Method A::mymethod() (and consequently, C::mymethod()) can't be const to be able to call the non-const method shared_from_this().
Preliminary problem: how do you down-cast to access myvar ?
Edit: after your edit, this first topic is no longer relevant. I leave it because I used this code in the live demos illustrating how to solve it.
First, the statement that causes the dump can't compile as you gave it:
std::cout << instance.pointer->myvar;
because instance.pointer is a shared_ptr<C> and C has no member myvar.
If downcasting properly with dynamic_pointer_cast<A>(instance.pointer)->myvar (supposing AnotherClass is a friend) it works.
Your shared pointer made a clone: is it your intent ?
This statement:
instance.pointer = std::make_shared<A>(*this); //is this wrong? PERHAP'S !?
creates a clone object obtained by copy construction from *this. So you don't reference the original object A, and hence you don't need std::enable_shared_from_this : the use count of instance.pointer will be 1 because at that moment there's only one reference to the newly created shared object.
Live demo
Or do you want it to reference the original object ?
You then have to change the statement to:
instance.pointer = std::shared_ptr<A>(this); //better ?
But this won't compile because mymethod() is const, so it consider this as being a pointer to const. To compile the statement you must either remove the constness of mymethod() or add constness to B's pointer.
Then it works. B's shared pointer has still a use count of 1, which is again ok. But once this shared_ptr gets out of scope, the use count is 0 and the shared_ptr's destructor will try to delete the object. AS IT WAS INITIALY A LOCAL OBJECT (ON STACK) this causes a runtime error.
Final approach
As you want to have shared pointers to your object, the code of AnotherClass should be something like:
shared_ptr<C> pobject(new A); // create the object from the free store
B instance = pobject->mymethod();
...
And the C class must inherit as follows:
class C : public std::enable_shared_from_this<C>
{...}
And the my method class must initialize the shared_pointer it retures as follows:
//instance.pointer = std::shared_ptr<A>(this); // no, don't do no longer !!
instance.pointer = shared_from_this(); //<===== RETURN A POINTER TO SELF
Then everything works perfectly.
Live demo
It seems to me that you would get a memory error when your objects go out of scope.
When you create your object A and then create your shared_ptr with the this pointer, your counter will be 1 instead of 2 (as you would maybe expect). So A will be destroyed twice, instead of once.
A more correct way of doing this would be create class A as a shared_ptr and initialize the pointer in class B with it (not inside class A). This way the counter will be incremented as you expect and A will be deleted only once.
The class you want to share will need to inherit from enable_share_from_this.
Then you can call share_from_this to obtain a shared pointer to the class you're in.
If you just try and make_shared you just create a separate ownership group that will mean two things will try and delete your object. That will be the cause of your segfault.
I have the following setup (simplified):
class A {
public:
void doBar() { B b; b.bar(); }
private:
int foo;
class B {
public: void bar() { /* do somehting with foo */ }
};
};
Now, VS tells me:
A non static member reference must be relative to a specific object
Well, okay, that sounds reasonable. However, as this class B is private to A I can be sure that it will never be used outside of an instance of a (specific) instance of A (okay, static methods of A are an exception).
So bottom line, is there any chance to get the current instance of A from a method of B, i.e., the instance from which B b was instantiated? I'm especially looking for a clean solution because otherwise I'd just pass in a reference.
Declaring a class within another class doesn't create "containment", only scope of the class declaration. Your B objects are not - generally speaking - contained by A objects, unless you make them so by virtue of how you hold references to each other.
So, no; there is no mechanism by which a B is able to determine which instance of A created it, because there is nothing special about this situation.
And think about it: the B object is created on the stack in your example, but it could have been heap-allocated. The A object might have also been created on the heap with 'new', or on the stack, or on a custom heap, or via 'placement-new'. There is no relation at all between the two objects in memory.
So I decided to use the Factory Design Pattern along with Dependency Injection.
class ClassA
{
Object *a, *b, *c;
public:
ClassA(Object *a, Object *b, Object *c) :
a(a), b(b), c(c) {}
};
class ClassB : public ClassA
{
Object *d, *e, *f;
public:
ClassB(Object *a, Object *b, Object *c, Object *d, Object *e, Object *f) :
ClassA(a, b, c), d(d), e(e), f(f) {}
};
Now, the problem is that classB has too many arguments for the constructor. This is a single inheritance-layer example, but when the inheritance layers start getting deeper, and when each layer-class needs more objects to be constructed, the constructor in the top layer ends requiring too many arguments in order to be made!
I know I could use setters instead of the constructor, but is there any other way?
Setter are not recommended for such things because they result in a partially constructed object which is very error prone. A common pattern for constructing an object that requires many parameters is the use of builder. The responsibility of ClassBBuilder is to create ClassB objects. You make ClassB constructor private and allow only builder to call it using friend relationship. Now, the builder can look somehow like this
ClassBBuilder {
public:
ClassBBuilder& setPhoneNumber(const string&);
ClassBBuilder& setName(consg string&);
ClassBBuilder& setSurname(const string&);
ClassB* build();
}
And you use the builder likes this:
ClassB* b = ClassBBuilder().setName('alice').setSurname('Smith').build();
build() method checks that all required parameters were set and it either returns properly constructed object or NULL. It is impossible to create partially constructed object. You still have a constructor with many arguments, but it is private and called only in a single place. Clients won't see it. Builder methods also nicely document what each parameter means (when you see ClassB('foo', 'bar') you need to check the constructor to figure out which parameter is a name and which is a surname).
This is one of the C++ problems (if this can be called a problem). It does not have solution other than trying to keep the number of parameters of the ctor minimal.
One of the approaches is using the props struct like:
struct PropsA
{
Object *a, *b, *c;
};
class ClassA
{
ClassA(PropsA &props, ... other params);
};
This seems obvious but I did used this several times. In many cases it turns out that some group of params are related. In this case it makes sense to define a struct for them.
My worst nightmare of this sort was with the thin wrapper classes. Methods and data fields of the base can be accessed directly while all ctors has to be duplicated. When there are 10+ ctors, creating a wrapper starts to be a problem.
I think what you're describing is not a problem in C++ - in fact, C++ reflects the dependencies expressed by your design fairly well:
To construct an object of type ClassA, you need to have three Object instances (a, b and c).
To construct an object of type ClassB, you also need to have three Object instances (d, e and f).
Every object of type ClassB can be treated like an object of type ClassA.
This means that for constructing an object of type ClassB you need to provide three Object objects which are needed for the implementation of the ClassA interface, and then another three for the implementation of the ClassB interface.
I believe the actual issue here is your design. You could consider different approaches to resolve this:
Don't let ClassB inherit ClassA. May or may not be an option depending on whether you need homogenous access to objects of either type (say, because you have a collection of ClassA* and this collection could also contain pointers to ClassB).
Look for objects which always appear together. Like - maybe the first two objects passed to either constructor (a and b or d and e) represent some sort of pair. Maybe an object identifier or the like? In this case, it may be beneficial to introduce a dedicated abstract (read: type) for this.