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.
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
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
A while ago I wrote some code with a set of nested classes. Looking over it today I'm wondering why it compiles when I instantiate an object of type C.
My confusion is this. B has a private constructor. The implementation of this constructor takes care of the construction of A, but the construction of A requires an instance of B. I feel like it's a chicken and the egg scenario. The construction of B requires the construction of A which requires the construction of B etc etc ad infinitum.
I have the following classes - stripped right back to demo the issue:
// ******* A ******** //
class A {
public:
A(A& _Parent, int id);
private:
A& Parent;
};
inline A::A(A& _Parent, int id)
: Parent(_Parent)
{
}
// ******* B ******** //
class B:public A {
public:
static B& GetInstance();
private:
B();
};
inline B::B()
: A(B::GetInstance(), 0)
{
}
inline B& B::GetInstance()
{
static B b;
return b;
}
// ******* C ******** //
class C:public A {
public:
C();
};
inline C::C()
: A(B::GetInstance(), 0)
{
}
Narrowing in on the problem:
inline B& B::GetInstance()
{
static B b;
return b;
}
inline B::B()
: A(B::GetInstance(), 0)
{
}
The line static B b; creates a B object the first time the function is called. However, the construction of b then calls GetInstance, which reaches the line static B b; while b is still under construction.
This case is covered by C++14 [stmt.dcl]/4:
[...] such a variable is considered initialized upon the completion of its initialization. [...] If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
I excised a part talking about what happens if an exception is thrown, or if two differently threads concurrently try to initialize the static variable. The standard does permit local static variables to be initialized prior to the first call of the function, but even if the implementation did that, the same problem would arise of control re-entering the declaration recursively.
Being undefined behaviour, anything can happen. One possible result is it appearing to work as intended. The standard does not require this to be diagnosed at compile-time -- a difficult thing to analyze. As indicated in comments, one version of gcc detects this at runtime and throws an exception. Perhaps your original compiler implements local statics by having a flag to indicate whether execution has reached that line yet, and it sets the flag before calling the constructor.
The rationale for having undefined behaviour in the standard is to avoid placing constraints on the way an implementation implements the well-defined behaviour (in this case, the method of ensuring local statics are only initialized once).
Of course, you should find a way to fix the problem as the undefined behaviour may manifest itself differently in future in ways that are hard to predict.
Although you didn't show any such code, let's assume something attempts to call the default constructor of C or in some other way calls B::GetInstance().
The first statement in GetInstance() is static B b;. Since this is the first time we've arrived here, the object b needs to be initialized by calling the default constructor B::B().
The first thing B::B() does is call GetInstance(), intending to then pass the result of that to the A::A(A&, int) constructor.
Which puts us back again at the statement static B b;. And the C++ Standard says ([stmt.dcl]/4):
Dynamic initialization of a block-scope variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization.... If control enters the declaration recursively while the variable is being initialized, the behavior is undefined.
Undefined behavior means anything could happen. It might appear to work, it might crash or hang your program, or it might initialize incorrectly and continue.
Suppose structs A and B are singleton structs defined as follows:
struct A
{
B& b_;
static A& shared_a() { ... }
A() : b_(B::shared_b()) { ... }
};
struct B
{
A& a_;
static B& shared_b() { ... }
B() : a_(A::shared_a()) { ... }
};
Suppose that the file structure is organized so that the code will compile.
The first time A::shared_a is called, it will construct the shared instance of A. The constructor for the shared instance of A will call B::shared_b, which will construct the shared instance of B. Next, the constructor for the shared instance of B will call A::shared_a. However, the shared instance of A has not finished its constructor! Therefore, these constructors will loop infinitely.
In order to prevent such a loop, I could merge classes A and B, but I would like to avoid doing so. Is there a more elegant solution?
Thanks,
Sam
Your code exhibits undefined behavior, and you might get either the infinite loop that you mention or any other weird behavior. Now, the problem is not with how to solve it, but rather break the cyclic dependency, which is usually a code smell.
If you are still convinced that your design makes sense, and if your constructors only store the references (without using the objects) you can change the constructors to take a reference to the object.
Again, I would avoid the cyclic dependency.
How about you give the shared_a() a reference of B itself so in the A_constructor of shared_a it can set that reference to be its b_?
lets say I have
class : foo
{
public:
static const foo Invalidfoo;
foo();
foo(int, string);
private:
int number;
std::string name;
};
Is it safe or prone to any problem?
EDIT :
I want to use this to have an invalid object to return as a reference to launch errors.
It is perfectly legal, but the following is better:
class foo:
{
public:
static const& foo Invalidfoo()
{
static foo Invalidfoo_;
return Invalidfoo_;
}
private:
foo();
};
This way you are guaranteed that the object is initialized the first time it is used.
Edit: But no matter how you do it, you still have a global object, and that can be a cause of problem. The best solution may be to call the default constructor each time you need a default constructed object. In terms of efficiency, the difference is probably negligable.
It's legal.
It's actually widely used in the singleton pattern
Singletons multi threading access and creation problems.
A nice article about this:
C++ and the Perils of Double-Checked Locking
It is just acting like a global variable or singleton. It's prone to the problems relating to those.
That is perfectly valid code. It doesn't have any reason to cause any problem, because static data members don't contribute to the size of the class. No matter how many static data members you define in a class, it doesn't change its size by even one byte!
struct A
{
int i;
char c;
};
struct B
{
int i;
char c;
static A a;
static B b;
};
In above code, sizeof(A) == sizeof(B) will always be true. See this demo:
http://www.ideone.com/nsiNL
Its supported by the section $9.4.2/1 from the C++ Standard (2003),
A static data member is not part of
the subobjects of a class. There is
only one copy of a static data member
shared by all the objects of the
class.
You cannot define non-static data member of the enclosing class type, because non-static members are parts of the object, and so they do contribute to the size of the class. It causes problem when calculating the size of the class, due to recursive nature of the data members.
See this topic:
How do static member variables affect object size?
It's legal. Terrible code from a practical/style point of view, but it is legal, and technically, it can be made to work. Better than Singleton because it's immutable.
This is actually how a singleton is implemented, except your static member would be a pointer. So yes, you're safe.