0

In which order will the ctors be called?

template<class T>
class A {
    public:
        static std::function<void(void)> funcobj;
};

template<class T>
std::function<void(void)> A<T>::funcobj = [](){};

class B : public A<B> {
    public:
        static const int i;

        B::B()
        { 
            DoSomethingHere(); 
        };
}inst;

std::function<void(void)> B::funcobj = [](){};

const int B::i = 2;

Am I right that the order will be something like this?
- const int B::i -> should be hardcoded in a data section of the PE file and thus doesn't need to be constructed at all?
- ctor of std::function for the initialization of A< B >::funcobj
- ctor of A
- ctor of std::function for the initialization of B::funcobj (though A< B >::funcobj and B::funcobj should be technically the same)
- ctor B::B

Grisu47
  • 530
  • 5
  • 16
  • 2
    why not you write a simple program that print in every C-tor to something unique to the console and check it your self? – NirMH May 04 '14 at 10:24
  • Like @NirMH says, why guess? Of course there's a reason for the specific order, and that might spawn a question, but the order itself is something you can produce, and contemplate. – keyser May 04 '14 at 10:27
  • 1
    Well there must be rules and reasons for the specific order and i'd like to know them. If you know how your compiler and linker work, you can take that into consideration and write better code. When i learned the basics of assembly language a while ago, it was the same. I didn't have to really use it a single time yet, but just knowing how things work at a lower level helped me to understand C++ a lot better – Grisu47 May 04 '14 at 10:33
  • Does that compile at all? I'd expect defining B::inst to cause an error. – Damon May 04 '14 at 11:31
  • It compiles with VS2013 Ultimate, but not with GCC4.7.2. I am using the class template A so every derivation of A has it's own funcobj whose value can be changed independently. Apart from that, I don't understand what problem you have with inst. Actually it's a static instance of B and thus a member of the global namespace, not B-namespace. – Grisu47 May 04 '14 at 11:58
  • To me this program is ill-formed and thus you have Undefined Behaviour if it compiles since you define `funcobj` multiple times :) – Drax May 06 '14 at 15:04
  • actually this design seems to be quite common for c++ devs. Originally I found the example for this on SO but I think it's the same here: http://blog.aaronballman.com/2011/08/static-polymorphism-in-c/ As @NirMH already suggested, I made a few tests with it and everytime the B::funcobj ctor was called, not the A::funcobj ctor. (well obviously it's the same function both times, but I used different parameters to determine which one was called) – Grisu47 May 06 '14 at 17:41

1 Answers1

1

First the static declarations will be executed in order. So:

template<class T> std::function<void(void)> A<T>::funcobj = [](){};
std::function<void(void)> B::funcobj = [](){};

const int B::i = 2;

(if B::i was an object type instead of an int then its constructor would have been called)

Then when it comes to initializing variable inst, it will start by initializing the parent class i.e. template class A's constructor will be called.

finally class B's constructor will be called.

radato
  • 840
  • 9
  • 27