Abstract member functions - strange phenomenon open to discussion:
-
Hi! I recently stumbled over this interesting phenomenon using abstract member functions: The situation is this: We have an abstract base class that defines an interface. In the constructor of the base, a specific implementation dependent task needs to be carried out, so an abstract member function is invoked in the constructor. The behaviour of this member function is defined by derived classes. If no function body is provided for this abstract function in the base class, a linker error occurs (unresolved symbol). If we provide an empty body, in the base, everything links fine and the vtable lookup correctly resolves the implementation of the deriving class. The question is this: If the abstract function is resolved at run-time anyway, through use of vtables, why give me a compile-time error if I don't provide a body that will, due to it being an abstract function, never be used in the first place?! Is this a Microsoft specific behaviour bug/"feature", or is this standard ISO behaviour? I compiled this using MS VS .NET 2003 Thanks for any thoughts about this. Nick Here is some exaple code for you to check it out:
#include class base { public: base() { abstractFunction(); } virtual ~base() {}; /* if you don't provide the function body with {}, a linker error occurs. Try uncommenting the part of the next line to make it work. */ virtual void abstractFunction() = 0 /*{}*/; }; class derived : public base { public: derived() {}; virtual ~derived() {}; // should be called by base::base() void abstractFunction() { printf("works\n"); } } testInstance; //create an instance right away...
This code should print "works" to the console, since the As soon as you uncomment the function body of base::abstractFunction(), everything will link fine and work as expected. -
Hi! I recently stumbled over this interesting phenomenon using abstract member functions: The situation is this: We have an abstract base class that defines an interface. In the constructor of the base, a specific implementation dependent task needs to be carried out, so an abstract member function is invoked in the constructor. The behaviour of this member function is defined by derived classes. If no function body is provided for this abstract function in the base class, a linker error occurs (unresolved symbol). If we provide an empty body, in the base, everything links fine and the vtable lookup correctly resolves the implementation of the deriving class. The question is this: If the abstract function is resolved at run-time anyway, through use of vtables, why give me a compile-time error if I don't provide a body that will, due to it being an abstract function, never be used in the first place?! Is this a Microsoft specific behaviour bug/"feature", or is this standard ISO behaviour? I compiled this using MS VS .NET 2003 Thanks for any thoughts about this. Nick Here is some exaple code for you to check it out:
#include class base { public: base() { abstractFunction(); } virtual ~base() {}; /* if you don't provide the function body with {}, a linker error occurs. Try uncommenting the part of the next line to make it work. */ virtual void abstractFunction() = 0 /*{}*/; }; class derived : public base { public: derived() {}; virtual ~derived() {}; // should be called by base::base() void abstractFunction() { printf("works\n"); } } testInstance; //create an instance right away...
This code should print "works" to the console, since the As soon as you uncomment the function body of base::abstractFunction(), everything will link fine and work as expected.You cannot call a virtual function of a derived class from a base class constructor. This is due to the order of construction. Base classes are built first so there is no vtable pointer available to call the correct function in the derived class, which is yet to be constructed. You need the function body as the virtual call compiles to the base class member function not the derived class one. You need a two stage construction method to handle what you need to do. x = new drieved; x.Initialise(); Where the initialise function calls the correct virtual functions once the object is fully constructed. If you vote me down, my score will only get lower
-
You cannot call a virtual function of a derived class from a base class constructor. This is due to the order of construction. Base classes are built first so there is no vtable pointer available to call the correct function in the derived class, which is yet to be constructed. You need the function body as the virtual call compiles to the base class member function not the derived class one. You need a two stage construction method to handle what you need to do. x = new drieved; x.Initialise(); Where the initialise function calls the correct virtual functions once the object is fully constructed. If you vote me down, my score will only get lower
Ah, I see. That escaped my attention. Quite obvious though, come to think of it. (->silly me) So the fact that my example code works OK is only by chance and not a regular case and more complicated classes or a release version compile might produce unpredictable results. Thanks for the comment. Nick