473,406 Members | 2,356 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Call virtual functions during construction

hello every body,
I know I shouldn't call virtual functions during construction or destruction.
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class   BaseWithPureFunction 
  5. public: 
  6.  
  7.  
  8.     virtual   void   PureFunc()   =   0; 
  9.     void   CallPureFunc()   
  10.     { 
  11.         PureFunc();     
  12.     } 
  13.  
  14.     BaseWithPureFunction() ;
  15. }; 
  16.  
  17.    BaseWithPureFunction::BaseWithPureFunction()   
  18.    /* 
  19.     Call pure-virtual via CallPureFun. 
  20.     Cause r6025 error.I have no question here.
  21.    */
  22.     CallPureFunc();   
  23.  
  24.  
  25. void BaseWithPureFunction::PureFunc()
  26. {
  27.    cout<<"Pure!"<<endl;
  28. }
  29.  
  30.  
  31.  
  32.  
  33. class   BaseEx:public   BaseWithPureFunction 
  34. public: 
  35.     virtual   void   PureFunc() 
  36.     { 
  37.         printf( "BaseEx::PureFunc()\r\n "); 
  38.     } 
  39. }; 
  40.  
  41. int _tmain(int argc, _TCHAR* argv[])
  42. {
  43.  
  44.    BaseEx ex;
  45.  
  46.    return 0;
  47. }
  48.  
  49.  
  50.  

If replace the BaseWithPureFunction function :
Expand|Select|Wrap|Line Numbers
  1.    BaseWithPureFunction::BaseWithPureFunction()   
  2.     /*
  3.       Call pure-virtual directly.
  4.       Running well.I puzzled.
  5.  
  6.     */
  7.           PureFunc();   
  8.  
  9. }
  10.  
  11.  
I puzzled why call pure-virtual directly, the programe won't cause error.I found some explanation in "Effective C++ Item 9".But I still think that this explanation is not detailed enough.
Aug 6 '10 #1

✓ answered by weaknessforcats

This is your code:
Expand|Select|Wrap|Line Numbers
  1. struct BaseWithPureFunction 
  2. {  
  3.     virtual void PureFunc() = 0; 
  4.  
  5.     void CallPureFunc() 
  6.     { 
  7.         PureFunc(); 
  8.     } 
  9.  
  10.     BaseWithPureFunction(); 
  11. }; 
  12.  
  13. BaseWithPureFunction::BaseWithPureFunction() 
  14.     PureFunc();//running well 
  15.     CallPureFunc(); //error. 
  16.   //Is there any difference between PureFunc and CallPureFunc. 
When you call PureFunc(), you really are calling
BaseWithPureFunction::PureFunc() because the virtual keyword is suspended inside a constructor.

However, when you are inside CallPureFunc() you may not be inside a constructor so when you call PureFunc() the VTBL is accessed and you bomb with a run-time error about calling a pure virtual function. All you need to do is tell the compiler to call the function without using the VTBL. That is, you need to specify the complete function name:

Expand|Select|Wrap|Line Numbers
  1. struct BaseWithPureFunction 
  2. {  
  3.     virtual void PureFunc() = 0; 
  4.  
  5.     void CallPureFunc() 
  6.     { 
  7.         BaseWithPureFunction::PureFunc(); 
  8.     } 
  9.  
  10.     BaseWithPureFunction(); 
  11. }; 
Now you are calling the function by name directly without using the VTBL. Now the program runs correctly.

11 1980
weaknessforcats
9,208 Expert Mod 8TB
Think about this.

When you have a virtual function, you instruct the compiler that when there is a choice between calling the base function or the derived function, the derived function is to be called.

Therefore, if you have:

class Base
{
public:
virtual void Method();
};
Aug 6 '10 #2
weaknessforcats
9,208 Expert Mod 8TB
Think about this.

When you have a virtual function, you instruct the compiler that when there is a choice between calling the base function or the derived function, the derived function is to be called.

However, during construction there is no guarantee that the derived object has been created yet. Therefore, when the base portion of the object is created, the call goes to the base virtual function.

The reverse appplies during destruction. Since the object is destroyed in reverse order, calling a virtual function in a destirctor results in a call to the local function since the derived portion of the object may have already been destroyed.

The net result is the the virtual keyword is ignored inside constructors and destructors.
Aug 6 '10 #3
Thanks for your help.
I know during construction the base virtual function will be called.So What you said is not that I want to know.
I want to find the answer :why this part of code can go well:
Expand|Select|Wrap|Line Numbers
  1. BaseWithPureFunction::BaseWithPureFunction()    
  2. {  
  3.     /* 
  4.       Call pure-virtual directly. 
  5.       Running well.I puzzled. 
  6.     */ 
  7.           PureFunc();    
  8.   } 
  9.  
In my opnion,it will cause r6025 error,too.But...
Aug 6 '10 #4
weaknessforcats
9,208 Expert Mod 8TB
You are creating a BaseEx object.

That object inherits BaseWithPureFunction::PureFunc.

You call BaseWithPureFunction::PureFunc from a BaseEx member function.

So what's the problem?

Remember, a pure virtual function cannot be called by an object of its class but it's OK to call it from some other object.

To enforce not calling BaseWithPureFunction::PureFunc using a BaseWithPureFunction object, the compiler will not allow you to create a BaseWithPureFunction object.

But can create a BaseEx object and call BaseWithPureFunction::PureFunc usign the BaseEx object.
Aug 7 '10 #5
The fact was that I called the function of PureFunc directly and by the CallPureFunc function indirectly had different results.One is running well,but the other cause a error.Tow ways both invoked PureFunc function by the same types of 'this' pointer that pointed to base type,but they had different results.
Is there any ambiguous?
Aug 8 '10 #6
weaknessforcats
9,208 Expert Mod 8TB
You should not be using CallWithPureFunc().

That function is a member function of the class BaseWithPureFunction and wghen you code:

Expand|Select|Wrap|Line Numbers
  1. BaseWithPureFunction  obj;
  2. obj.CallWithPurFunc();
you a compile error that you can't create an object of an abstract class because you can't use a BaseWithPureFunction object to call a pure virtual function in the BaseWithPureFunction class.

However, you can code:

Expand|Select|Wrap|Line Numbers
  1. BaseEx  obj;
  2. obj.BaseWithPureFunction::PureFunc();
to call PureFunc using a BaseEx object.

You could also:

Expand|Select|Wrap|Line Numbers
  1. BaseEx obj1;
  2. obj1.PureFunc();
but no it's not cleas whether BaseEx::PureFunc() or BaseWithPureFunction::PureFunc() is being called unless you look in the code and see. Therefore, this is the preferred code:

Expand|Select|Wrap|Line Numbers
  1. BaseEx  obj;
  2. obj.BaseWithPureFunction::PureFunc();
Aug 9 '10 #7
Thanks again for your help.
At the point the base class constructor is invoked from the derived class constructor, the object ex is not yet of type BaseEx.The base class constructor initializes the BaseWithPureFunction subobject within ex to behave like a BaseWithPureFunction object. Therefore, when the virtual PureFunc is called in base class constructor, it binds to BaseWithPureFunction::PureFunc.According to holy,it should lead a error.But when I running this code it goes well.
So I altered BaseWithPureFunction constructor I made it invoke the BaseWithPureFunction::CallPureFunc.Then the virtual function PureFunc will be invoked by CallPureFunc.
When I running the code I have altered,a r6025 error appeared.
Two kinds of codes are both equal to using a BaseWithPureFunction object-a base object- to call a pure virtual function .
So I begin to think why two kinds of codes will lead differernt results.
Aug 10 '10 #8
weaknessforcats
9,208 Expert Mod 8TB
The virtual keyword is suspended in constrcutors and destructors. It's like its not there.

Re-read my post #3.
Aug 10 '10 #9
...My question has been answered?May be my expression is unclear.
Please look at the question again,and make sure what I want to know.Thank you.
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. struct BaseWithPureFunction
  5.     virtual void PureFunc() = 0;
  6.  
  7.     void CallPureFunc()
  8.     {
  9.         PureFunc();
  10.     }
  11.  
  12.     BaseWithPureFunction();
  13. };
  14.  
  15. BaseWithPureFunction::BaseWithPureFunction()
  16. {
  17.     PureFunc();//running well
  18.     CallPureFunc(); //error.
  19.   //Is there any difference between PureFunc and CallPureFunc.
  20. }
  21.  
  22. void BaseWithPureFunction::PureFunc()
  23. {
  24.     cout << 3 << endl;
  25. }
  26.  
  27. struct BaseEx : BaseWithPureFunction
  28.     virtual void PureFunc()
  29.     {
  30.         cout << "BaseEx::PureFunc()" << endl;
  31.     }
  32. };
  33.  
  34. int main()
  35. {
  36.     BaseEx ex;
  37.  
  38.     return 0;
  39. }
  40.  
  41.  
Aug 11 '10 #10
weaknessforcats
9,208 Expert Mod 8TB
This is your code:
Expand|Select|Wrap|Line Numbers
  1. struct BaseWithPureFunction 
  2. {  
  3.     virtual void PureFunc() = 0; 
  4.  
  5.     void CallPureFunc() 
  6.     { 
  7.         PureFunc(); 
  8.     } 
  9.  
  10.     BaseWithPureFunction(); 
  11. }; 
  12.  
  13. BaseWithPureFunction::BaseWithPureFunction() 
  14.     PureFunc();//running well 
  15.     CallPureFunc(); //error. 
  16.   //Is there any difference between PureFunc and CallPureFunc. 
When you call PureFunc(), you really are calling
BaseWithPureFunction::PureFunc() because the virtual keyword is suspended inside a constructor.

However, when you are inside CallPureFunc() you may not be inside a constructor so when you call PureFunc() the VTBL is accessed and you bomb with a run-time error about calling a pure virtual function. All you need to do is tell the compiler to call the function without using the VTBL. That is, you need to specify the complete function name:

Expand|Select|Wrap|Line Numbers
  1. struct BaseWithPureFunction 
  2. {  
  3.     virtual void PureFunc() = 0; 
  4.  
  5.     void CallPureFunc() 
  6.     { 
  7.         BaseWithPureFunction::PureFunc(); 
  8.     } 
  9.  
  10.     BaseWithPureFunction(); 
  11. }; 
Now you are calling the function by name directly without using the VTBL. Now the program runs correctly.
Aug 11 '10 #11
I finally understand.
Thank you very much indeed .
Aug 14 '10 #12

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: mescaline | last post by:
If a function is declared a virtual function, in what cases will (some) compilers still do static binding? thanks
25
by: Stijn Oude Brunink | last post by:
Hello, I have the following trade off to make: A base class with 2 virtual functions would be realy helpfull for the problem I'm working on. Still though the functions that my program will use...
23
by: heted7 | last post by:
Hi, Most of the books on C++ say something like this: "A virtual destructor should be defined if the class contains at least one virtual member function." My question is: why is it only for...
3
by: marcwentink | last post by:
Say I have a class A, and a class B that inherits from A. Now A (and B) has a virtual destructor and a virtual function F(); If I now make these statements A* ptrA = new B; ptrA->F(); delete...
7
by: vaividhya | last post by:
We can have virtual destructors.Why we can't have virtual constructors?
6
by: Henrik Goldman | last post by:
Hi I've had a problem with gcc mac osx which I think I figured out. I would like to double check with people here to see if my understanding is correct: I have a class A which class B inherit...
7
by: vabby | last post by:
Hi I have run into an eerie situation whihc i cant make out. I have a class A which has has two virtual functions with the same name, having diff arguments. Basically a case of function...
7
by: v4vijayakumar | last post by:
Is it possible to implement member object's virtual functions, in the containing class? If not, is it possible to simulate this behavior? ex: class test { protected: virtual void fun() = 0;...
17
by: Jess | last post by:
Hello, If I have a class that has virtual but non-pure declarations, like class A{ virtual void f(); }; Then is A still an abstract class? Do I have to have "virtual void f() = 0;"...
8
by: siddhu | last post by:
Dear experts, A virtual function has to have an address. So if an inline virtual function is actually inlined then in that case what does address of this function signify? How does compiler know...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.