There's some code at my company that takes the following form:
class ObjectA {
public:
ObjectA(ObjectB &objectB): objectB(objectB) { }
void Initialize() { ... }
private:
ObjectB &objectB;
};
class ObjectB {
public:
ObjectB(ObjectA &objectA): objectA(objectA) { }
void Initialize() { ... }
private:
ObjectA &objectA;
};
Basically, two classes have a mutual dependency on the other.
This in itself isn't what bothers me, (although it's not great design IMO), it's that the mutual dependencies are passed through the constructor by reference in both situations.
So, the only way to actually construct this pair of objects (they are both required in the application) is to pass an incomplete reference as a dependency. To account for this, the separate Initialize methods are added as a 2nd stage constructor which are then called after both objects are created. Consequently, the constructors often times do nothing except assign the constructor parameters to the object internals, and initialize everything in the Intizialize method.
Although the code may be valid, my inclination is that this is a fundamentally flawed design for the following reasons:
The state of a dependent object can't be guaranteed in the
constructor
It requires the developers to make an additional call to Initialize
It precludes the use of compiler warnings that check if member variables have been initialized
There's nothing preventing Initialize from being called multiple times, which can result in strange, hard to track down errors
My coworkers tell me that having a separate initialize method simplifies the object construction since the developer doesn't have to worry about what order objects are declared in the application root. They can be declared and constructed in completely arbitrary order since everything is guaranteed to be valid once Initialize gets called.
I've been advocating that object construction should follow the same order of the dependency graph and that these objects should be redesigned to remove the mutual dependency, but I wanted to see what the SO gurus had to say about it. Am I wrong to think this is bad practice?
Edit:
The way these classes actually get constructed is through a factory class like below:
Factory {
public:
Factory():
objectA(objectB),
objectB(objectA) {
}
private:
ObjectA objectA;
ObjectB objectB;
};
This is bad practice yes. Passing a reference to objectB for objectA to work with while it's not properly initialized yet is a no-no.
It might be standard compliant and safe code now because ObjectA doesn't try to access the passed reference to ObjectB in its constructor but that safety is hanging by a thread. If later on someone decides to just initialize in the constructor or access anything from objectB, or change it any other way where objectB will be used you end up with UB.
This sounds like a use case for pointers that are reseated after both constructors have run.
I too don't like the code as posted - it is unnecessarily complicated and fragile. There is usually some concept of ownership when two classes cooperate like this, so, if objects of type A own objects of type B (which they probably should), then you would do something like:
#include <memory>
class A;
class B
{
public:
B (A& a) : a (a) { }
private:
A& a;
};
class A
{
public:
A () { b = std::make_unique <B> (*this); }
private:
std::unique_ptr <B> b;
};
Live demo
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 have two classes
class A {
public:
virtual void doStuff() = 0;
};
class B : public A {
int x;
public:
virtual void doStuff() override { x = x*2;} //just example function
};
And another class that modify and use data from the previous
class Foo {
A a;
public:
Foo::Foo(A &a_) : a(a_) {}
};
now I create the objects, and passes to the Foo class
B b;
// edit b attributes,
Foo foo(b);
So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?
Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.
Will there be a object slicing?,
Is there a solution to this, or I need to pass pointers (don't want this approach)?
This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.
In fact:
class Foo {
A a;
that won't even compile, because A is not a concrete class.
To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.
Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.
This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.
All of this is harder than just using the built in C++ object model directly, but it can have payoff.
To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.
There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors.
Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.
You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.
Yes, there is slicing.
There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.
I have recently started using init methods instead of passing parameters to the constructor when designing classes in C++:
Class A {
public:
A();
init(int number);
...
};
Instead of:
Class A {
public:
A(int number);
};
This allows me to use A as a member in other classes like this:
class B {
A m_a;
};
Instead of the way I used to do it:
class B {
A *m_a;
};
(and then allocate m_a in B's constructor.)
The good thing about using init functions is that I don't have to worry about deleting m_a since it will be destroyed when the instance of B is destroyed.
My question is: Is there any downside to using init-methods that I should know about? Will this overflow the stack etc?
Everything is working fine so far, but I thought that I should ask before I write to much code in this way.
It's a horrible pattern.
The object will be in an undefined state between its construction and your calling init. Also you have to think about making init thread safe, along with making init robust if called more than once.
Also note that you can call a constructor from another one from c++11 onwards. So the argument that an init function eliminates duplication of code that could arise from having multiple constructors no longer applies.
You're not obliged to use pointers to have class instances as attributes.
Class B {
public:
explicit B(int i); // notice the explicit, btw
A m_a;
};
B::B(int i)
: m_a(i) { // will call the constructor of "A" with "i" as argument
}
m_a will be destroyed when the instance of B is destroyed too.
By adding an init method, you're defeating the purpose of constructors: you can have an object that's not fully built. Instead of forgetting to delete m_a, you take the risk to forget to init it.
You can store properties by value even if you need non-default constructor to instantiate them. In the constructor of class B you'll need to explicitly instantiate the m_a via intialization list, e.g. B(int number):m_a(number){}. Using initialization functions to overcome this "problem" is really unnecessary here as the language supports this natively.
I have two classes A and B such that A has a static B instance as its member. B has a function Show() and here is my class A:
class A
{
A()
{
_b.Show();
}
private:
static B _b;
};
and subsequent code is
A a;
B A::_b;
int main()
{
}
Now B::Show() called before B is constructed due to the sequence in which I have defined
a and _b. But how does this work exactly i.e. how is it possible to make calls on an object that is still not constructed ?
It's not possible, it's undefined behavior (in this case, because you're accessing an uninitialized object) because a is initialized before A::_b.
Look up static initialization order fiasco. You don't get an error because 99% of the times this happens, it's not easily diagnosable.
This is the static initialisation order problem. Hard to solve in the general case, but one way to fix some cases is to put the dependency inside a function like this:
class A
{
public:
A()
{
getB().Show();
}
private:
static B& getB()
{
static B b;
return b;
}
};
statics within functions are guaranteed to be initialised the first time that a call is made to it. Additionally in C++11 this is guaranteed to be thread safe as well.
Further reading:
http://www.parashift.com/c++-faq/static-init-order-on-first-use.html
Finding C++ static initialization order problems
how is it possible to make calls on an object that is still not
constructed?
Well, the simple answer is, exactly the way that code does it. <g>. Objects defined at file scope in the same translation unit are constructed in the order in which their definitions occur, so if the constructor of one object relies on another object, you have to ensure that the second object has already been constructed when the constructor for the first object runs.
C++ doesn't offer any help here; you have to keep track of it yourself.
I am working on a legacy framework. Lets say 'A' is the base-class and 'B' is the derived class. Both the classes do some critical framework initialization. FWIW, it uses ACE library heavily.
I have a situation wherein; an instance of 'B' is created. But the ctor of 'A' depends on some initialization that can only be performed from 'B'.
As we know when 'B' is instantiated the ctor for 'A' is invoked before that of 'B'. The virtual mechanism dosen't work from ctors, using static functions is ruled-out (due to static-initialization-order-fiasco).
I considered using the CRTP pattern as follows :-
template<class Derived>
class A {
public:
A(){
static_cast<Derived*>(this)->fun();
}
};
class B : public A<B> {
public:
B() : a(0) {
a = 10;
}
void fun() { std::cout << "Init Function, Variable a = " << a << std::endl; }
private:
int a;
};
But the class members that are initialized in the initializer list have undefined values as they are not yet executed (f.e. 'a' in the above case). In my case there a number of such framework-based initialization variables.
Are there any well-known patterns to handle this situation?
Thanks in advance,
Update:
Based on the idea given by dribeas, i conjured-up a temporary solution to this problem (a full-fledged refactoring does not fit my timelines for now). The following code will demonstrate the same:-
// move all A's dependent data in 'B' to a new class 'C'.
class C {
public:
C() : a(10)
{ }
int getA() { return a; }
private:
int a;
};
// enhance class A's ctor with a pointer to the newly split class
class A {
public:
A(C* cptr)
{
std::cout << "O.K. B's Init Data From C:- " << cptr->getA() <<
std::endl;
}
};
// now modify the actual derived class 'B' as follows
class B : public C, public A {
public:
B()
: A(static_cast<C*>(this))
{ }
};
For some more discussion on the same see this link on c.l.c++.m. There is a nice generic solution given by Konstantin Oznobikhin.
Probably the best thing you can do is refactoring. It does not make sense to have a base class depend on one of its derived types.
I have seen this done before, providing quite some pain to the developers: extend the ACE_Task class to provide a periodic thread that could be extended with concrete functionality and activating the thread from the periodic thread constructor only to find out that while in testing and more often than not it worked, but that in some situations the thread actually started before the most derived object was initialized.
Inheritance is a strong relationship that should be used only when required. If you take a look at the boost thread library (just the docs, no need to enter into detail), or the POCO library you will see that they split the problem in two: thread classes control thread execution and call a method that is passed to them in construction: the thread control is separated from the actual code that will be runned, and the fact that the code to be run is received as an argument to the constructor guarantees that it was constructed before the thread constructor was called.
Maybe you could use the same approach in your own code. Divide the functionality in two, whatever the derived class is doing now should be moved outside of the hierarchy (boost uses functors, POCO uses interfaces, use whatever seems to fit you most). Without a better description of what you are trying to do, I cannot really go into more detail.
Another thing you could try (this is fragile and I would recommend against) is breaking the B class into a C class that is independent of A and a B class that inherits from both, first from C then from A (with HUGE warning comments there). This will guarantee that C will be constructed prior to A. Then make the C subobject an argument of A (through an interface or as a template argument). This will probably be the fastest hack, but not a good one. Once you are willing to modify the code, just do it right.
First, I think your design is bad if the constructor of a base class depends on the something done in the constructor in a derived. It really shouldn't be that way. At the time the constructor of the base class run, the object of the derived class basically doesn't exist.
A solution might be to have a helper object passed from the derived class to the constructor of the base class.
Perhaps Lazy Initialization does it for you. Store a flag in A, wether it's initialized or not. Whenever you call a method, check for the flag. if it's false, initialize A (the ctor of B has been run then) and set the flag to true.
It is a bad design and as already said it is UB. Please consider moving such dependencies to some other method say 'initialize' and call this initialize method from your derived class constructor (or anywhere before you actually need the base class data to be initialized)
Hmm. So, if I'm reading into this correctly, "A" is part of the legacy code, and you're pretty damn sure the right answer to some problem is to use a derived class, B.
It seems to me that the simplest solution might be to make a functional (non-OOP) style static factory function;
static B& B::makeNew(...);
Except that you say you run into static initialization order fiasco? I wouldn't think you would with this kind of setup, since there's no initialization going on.
Alright, looking at the problem more, "C" needs to have some setup done by "B" that "A" needs done, only "A" gets first dibs, because you want to have inheritance. So... fake inheritance, in a way that lets you control construction order...?
class A
{
B* pB;
public:
rtype fakeVirtual(params) { return pB->fakeVirtual(params); }
~A()
{
pB->deleteFromA();
delete pB;
//Deletion stuff
}
protected:
void deleteFromB()
{
//Deletion stuff
pB = NULL;
}
}
class B
{
A* pA;
public:
rtype fakeInheritance(params) {return pA->fakeInheritance(params);}
~B()
{
//deletion stuff
pA->deleteFromB();
}
protected:
friend class A;
void deleteFromA()
{
//deletion stuff
pA = NULL;
}
}
While it's verbose, I think this should safely fake inheritance, and allow you to wait to construct A until after B has done it's thing. It's also encapsulated, so when you can pull A you shouldn't have to change anything other than A and B.
Alternatively, you may also want to take a few steps back and ask yourself; what is the functionality that inheritance gives me that I am trying to use, and how might I accomplish that via other means? For instance, CRTP can be used as an alternative to virtual, and policies an alternative to function inheritance. (I think that's the right phrasing of that). I'm using these ideas above, just dropping the templates b/c I'm only expecting A to template on B and vice versa.