Click here to Skip to main content
15,064,293 members
Please Sign up or sign in to vote.
3.67/5 (3 votes)
See more:
class A{
public:
	A(){msg();}
	virtual void msg(){AfxMessageBox(_T("A"));}
};

class B: public A{
public:
	B():A(){}
private:
	virtual void msg(){AfxMessageBox(_T("B"));}
};

void test(){
	B b;	//will Message("A");  -------why? I think I can get Message("B")!-----

	A*pA=&b;
	pA->msg();//will Message("B");
}
Posted
Comments
Maciej Los 22-Aug-13 5:40am
   
And where is a question?
Thanks7872 22-Aug-13 5:41am
   
That's the puzzle. :(
Maciej Los 22-Aug-13 5:46am
   
;)
Stefan_Lang 22-Aug-13 7:39am
   
It is in the comments, first line of function test().
Richard MacCutchan 22-Aug-13 5:46am
   
This is easy enough to test for yourself.
pasztorpisti 22-Aug-13 6:03am
   
I don't think so... ;-)
Richard MacCutchan 22-Aug-13 6:09am
   
It took me less than 2 minutes.
pasztorpisti 22-Aug-13 6:16am
   
This will print "A" and then "B". The question of OP is why does it print "A" as the first message. Its not trivial at all and most C++ programmers unfortunately don't know the answer to this question. I have fixed a lot of bugs as a result of this.
Richard MacCutchan 22-Aug-13 6:23am
   
I didn't say it was trivial, I said it was easy to test. OP's message was not clear, so I had thought it was more of a "what will happen?".
pasztorpisti 22-Aug-13 7:10am
   
The question is indeed unusually embedded as a comment.

Quote:
B b; //will Message("A"); -------why? I think I can get Message("B")!-----
B constructor explicitely calls the A constructor, hence you get such a message.

Sorry, that was wrong, as pasztorpisti pointed out. You may find correct info here:
C++ FAQ: [23.5] When my base class's constructor calls a virtual function on its this object, why doesn't my derived class's override of that virtual function get invoked?[^]



Quote:
pA->msg();//will Message("B");
This is the usual polimorphic behaviour.
   
v2
Comments
pasztorpisti 22-Aug-13 6:14am
   
No, the message "A" is a bug in the code and it has nothing to do with the explicit call. The explicit call does exactly the same that the auto-generated ctor upcall would do.
CPallini 22-Aug-13 7:15am
   
You are right I have updated my answer.
Stefan_Lang 22-Aug-13 7:36am
   
Great link. I thought to look that one up when I saw the question, but you obviously beat me to it :-)

P.S.: upvoted on the basis of version 2
CPallini 22-Aug-13 8:02am
   
Thank you.
pasztorpisti 22-Aug-13 7:53am
   
+5, much better now :-)
CPallini 22-Aug-13 8:02am
   
Thank you.
EDIT: Richard MacCutchan came up with a good idea of writing a tip/trick about this problem. I've just put together a small discussion with example code about this problem: Never call virtual methods from the constructor or destructor of your classes in C++/C#/Java![^]

I am lazy to write here the answer again as I have already answered this question a few times. The reason in a few words: Never call virtual methods directly or indirectly from (base class) constructors. Please read my posts regarding this:

http://www.codeproject.com/Messages/4619258/Re-Serial-Port-OK-in-class-constructor-but-not-out.aspx[^]
http://www.codeproject.com/Messages/4619708/Re-Serial-Port-OK-in-class-constructor-but-not-out.aspx[^]
   
v2
Comments
Stefan_Lang 22-Aug-13 7:35am
   
That first link is a bit ... compressed and may require checking previous parts of that thread. I'll give you a 5 for that second link however. Great posting.
pasztorpisti 22-Aug-13 7:51am
   
Thank you!
CPallini 22-Aug-13 8:02am
   
5.
pasztorpisti 22-Aug-13 8:06am
   
Thank you!
Richard MacCutchan 22-Aug-13 8:10am
   
5: The description in link 2 deserves publication as a Tip at the least.
pasztorpisti 22-Aug-13 8:12am
   
Good idea! A virtual +5. :-)
H.Brydon 25-Aug-13 22:29pm
   
[The only answer I give a +5, for the text "never call virtual functions from constructors..."]. IMHO a constructor should never call them, and any articles about doing it are really academic. My recommendation is to not call anything in the same class hierarchy except a private non-virtual method or (C++11) a delegating constructor.
pasztorpisti 26-Aug-13 5:54am
   
Thank you! Some people were uncomfortable about the "Never call..." stuff (so I adjusted the title of the final version) and I understand that to some degree because making it forbidden to use a core language feature is a bit strange. I rather made some language-specific recommendations. Still I think its a good practice to do what you have described, I've never been in the need of calling a virtual method in a constructor but I've fixed a lot of related bugs in C++ and debugged for a whole day in java to find my first related bug (because I've put a breakpoint in a derived virtual method, I've seen a lot of null member variables but I didn't expect the method call before the ctor so I was in a "WTF state" before finding out that the ctor hasn't yet been executed...).

In C++ calling a virtual method from ctor is basically a bug. It would be nice to be able to tell the compiler to generate the following ctor:
constructor()
{
auto generated: call the base class constructor (if we have a base class)
auto generated: initialize the table pointer to the fake-assert-vtable of this class
[your constructor code here]
auto generated: initialize the table pointer to the real-vtable of this class
}

This way your ctor code would be executed with a fake-assert-vtable that could help in catching most of these "bugs" at least at runtime when you create an instance... (because calling any virtual methods from the fake-assert-vtable would fire an assert.)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900