1

In the following code :

#include <iostream>
using namespace std;

template<class T >
class Setting
{
public:
    Setting(Setting* instance){
        ((T*)instance)->write();
    };
    Setting(){ write(); };
    virtual void write(){ cout << "in parent\n"; }
};

class child :public Setting<child>
{
public:
    child() :Setting(this){};
    virtual void write(){ cout << "in child\n"; }
};
int main()
{
    child ch;
}

g++ prints "in child" which is exactly what I want .( http://coliru.stacked-crooked.com/a/4304ab99ebd894b3)

But in visual studio 2013 output is "in parent" !!!(http://rextester.com/EMQ5448)

why?? Is there any alternative way for getting the same result in visual studio?

uchar
  • 2,552
  • 4
  • 29
  • 50
  • Try a `static_cast(instance)` or even simpler (without need for `instance`): `static_cast(this)` – πάντα ῥεῖ Dec 23 '14 at 14:16
  • 1
    it is I believe nothing to do with visual studio but `visual c++` – Tolga Evcimen Dec 23 '14 at 14:18
  • 2
    http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors mvcc is not a standard complaint compiler. In general, calling virtual functions from the constructor has a pretty bad code smell... – IdeaHat Dec 23 '14 at 14:21
  • `Setting(){ static_cast(this)->write(); };` – πάντα ῥεῖ Dec 23 '14 at 14:21
  • 1
    @πάνταῥεῖ not working http://rextester.com/OPX32838 – uchar Dec 23 '14 at 14:27
  • 1
    Your code is wrong, it shouldn't work like you wish, looks like gcc 4.9 bug. What are you trying to do? – ForEveR Dec 23 '14 at 14:35
  • @omid Remove the `virtual` from the `write` signatures and [it works](http://rextester.com/XDU51563) as you expect it! Take some time an read about how CRTP is intended to work. – πάντα ῥεῖ Dec 23 '14 at 14:41
  • @ForEveR I want to call virtual functions in base class constructor for initializing some member variable . I want a better way of designing my class instead of duplicating the same code for childs . http://coliru.stacked-crooked.com/a/96c1fd34299c9f9b – uchar Dec 23 '14 at 14:43
  • @omid You can't call virtual functions from a base class constructor, period. – πάντα ῥεῖ Dec 23 '14 at 14:44
  • 1
    @omid you can't. Instead write function in base, that should be called in derived c-tor. http://coliru.stacked-crooked.com/a/44cea00d71c4b641 – ForEveR Dec 23 '14 at 14:50

1 Answers1

1

"why?? Is there any alternative way for getting the same result in visual studio?"

Because compiler implementations seem to differ when handling this syntax.
It seems like if write() is declared as a virtual function, VS2013 always tries to resolve it from the vtable, instead of using the method from the (not yet) instantiated derived class (disrespecting the static_cast<>).

I've got your sample working when removing the virtual keywords from your write() function declarations, like this

template<class T >
class Setting {
public:
    Setting(){ static_cast<T*>(this)->write(); };

    void write(){ cout << "in parent\n"; } // Note: No virtual
};

class child :public Setting<child> {
public:
    child() {};
    void write(){ cout << "in child\n"; }  // Note: No virtual
};

int main() {
    child ch;
}

Though this works, you seriously should obey, not to rely on any state established from the child class constructor, when calling write from the base class.


You also want to read about some additional references what the CRTP pattern, and using static polymorphism (that's all about avoiding the virtual) actually is about.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190