#include <stdio.h>
struct ClassDay
{
virtual void say();
ClassDay();
};
struct ClassMorning : ClassDay
{
virtual void say();
};
void ClassMorning::say(){ printf("Good morning!"); }
void ClassDay::say(){ printf("Hello!"); }
ClassDay::ClassDay(){ say(); }
void main()
{
ClassMorning test;
getchar();
}
I hope you can help :)
Constructor calling a virtual method
Hi! I simplified my problem a bit, so it is easier to understand. I have a simple base class with a certain virtual method. The constructor of that class calls the method and that's all. Now I derive another class from that base class which overrides the virtual method.
What I expected when initializing the derived class was to get the output from the derived method. In fact the method from the base class was called.
I think this behaviour is quite astonishing and therefore I just wanted to know why that happens and how I can fix this.
A small example:
This is intended behavior. When the base class constructor is being run, virtual function calls will use the base class versions. The reason for this is that derived class functions may access data members that don't exist in the base class. Ex:
What happens if Derived::f() is called in the Base class? data hasn't been constructed yet, so the assignment may die a horrible death.
struct Base { Base() { f(); } virtual void f(void) {}};struct Derived : Base { std::string data; void f(void) { data = "fred"; }}
What happens if Derived::f() is called in the Base class? data hasn't been constructed yet, so the assignment may die a horrible death.
I think I know the reason for this behaviour now. It is logical that the base constructor does not know anything about the children's methods, because it is called before the children's constructors. Therefore it calls the known method and the derived one is ignored.
Nevertheless I have no idea how to cope with the problem...
Nevertheless I have no idea how to cope with the problem...
The .net c# compiler issues a warning when you call a virtual method from the constructor. Embarrassingly enough, our currently project at work heavily shows this bad practice (and at least some of the fault is mine :-(
We have had a few problems with it (now addresed) and thus I highly encourage to avoid that at all.
My 2 cents.
We have had a few problems with it (now addresed) and thus I highly encourage to avoid that at all.
My 2 cents.
This is as expected. ClassMorning haven't been constructed yet, so its generally not safe to call it if it would be possible. I refer to c++ faq lite.
http://new-brunswick.net/workshop/c++/faq/ctors.html#faq-10.7
"Here is something that never works: the {body} of a constructor (or a function called from the constructor) cannot get down to a derived class by calling a virtual member function that is overridden in the derived class. If your goal was to get to the overridden function in the derived class, you won't get what you want. Note that you won't get to the override in the derived class independent of how you call the virtual member function: explicitly using the this pointer (e.g., this->method()), implicitly using the this pointer (e.g., method()), or even calling some other function that calls the virtual member function on your this object. The bottom line is this: even if the caller is constructing an object of a derived class, during the constructor of the base class, your object is not yet of that derived class. You have been warned."
Workaround would be to pass the data that is needed from the derived class or to write your own init method which you call after construction.
http://new-brunswick.net/workshop/c++/faq/ctors.html#faq-10.7
"Here is something that never works: the {body} of a constructor (or a function called from the constructor) cannot get down to a derived class by calling a virtual member function that is overridden in the derived class. If your goal was to get to the overridden function in the derived class, you won't get what you want. Note that you won't get to the override in the derived class independent of how you call the virtual member function: explicitly using the this pointer (e.g., this->method()), implicitly using the this pointer (e.g., method()), or even calling some other function that calls the virtual member function on your this object. The bottom line is this: even if the caller is constructing an object of a derived class, during the constructor of the base class, your object is not yet of that derived class. You have been warned."
Workaround would be to pass the data that is needed from the derived class or to write your own init method which you call after construction.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement