Click here to Skip to main content
15,881,967 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
AnswerRe: Visual Studio 2010 optimized code bug Pin
Richard MacCutchan10-Feb-13 21:49
mveRichard MacCutchan10-Feb-13 21:49 
GeneralRe: Visual Studio 2010 optimized code bug Pin
ForNow11-Feb-13 17:17
ForNow11-Feb-13 17:17 
GeneralRe: Visual Studio 2010 optimized code bug Pin
Richard MacCutchan11-Feb-13 22:10
mveRichard MacCutchan11-Feb-13 22:10 
GeneralRe: Visual Studio 2010 optimized code bug Pin
ForNow12-Feb-13 2:25
ForNow12-Feb-13 2:25 
Question__interface implies the novtable __declspec modifier Pin
bob169729-Feb-13 11:30
bob169729-Feb-13 11:30 
AnswerRe: __interface implies the novtable __declspec modifier Pin
H.Brydon9-Feb-13 18:35
professionalH.Brydon9-Feb-13 18:35 
GeneralRe: __interface implies the novtable __declspec modifier Pin
bob1697210-Feb-13 5:20
bob1697210-Feb-13 5:20 
AnswerRe: __interface implies the novtable __declspec modifier Pin
pasztorpisti9-Feb-13 23:32
pasztorpisti9-Feb-13 23:32 
novtable is used in case of hardcore optimizations with "abstract" base classes are never instantiated. An interface is always abstract by definition.

To understande novtable first you have to understand a bit more about how a derived class is instantiated and initialized. Let me explain this with a simple example:
  A
 / \
B   C
   / \
  D   E

The above drawing is a class hierarchy and we will examine the instantiation of the D class. Lets assume that A already has at least one virtual method so it has a vtable as well. What you have learnt about C++ is that "new D;" calls constructors A, C and D in this order. Now we delve into the implementation details and check out some interesting stuff. The simple truth is that the only thing that the compiler calls in case of "new D;" is the constructor of D. BUT every constructor starts with some auto generated stuff by the compiler that is followed by the "user defined constructor code".
Let's see some pseudo code:
C++
constructor_D()
{
   auto-generated: call constructor_C()
   auto-generated: init the vtable to vtable-D
   user-defined constructor code of D
}

constructor_C()
{
   auto-generated: call constructor_A()
   auto-generated: init the vtable to vtable-C
   user-defined constructor code of C
}

constructor_A()
{
   auto-generated: init the vtable to vtable-A
   user-defined constructor code of A
}

So if we consider only the "user defined constructor code" then the order of constructor calls is indeed A C D, but if we look at the whole stuff then its D C A. Its obvious that initializing the vtable more than once for an instance is superfluous, in the above example its initialzed 3 times, first in A, then in C and finially in D. We need the initialization only in D because we created a D instance so we need the virtual methods for the D class. Unfortunately sometimes the compiler can not find out whether the vtable initialization in A and C are superfluous or not so it generates the vtable init code there, but you can add the novtable to class A and C as an optimization if you know that they will never be instantiated. In case of an interface we know that it will never be instantiated so an automatic novtable optimization is obvious, an interface will have at least one descendant to init the final vtable pointer.

In your example the ISample interface simply doesn't have a constructor and your CSample constructor looks like this:
constructor_CSample()
{
   auto-generated: init the vtable to vtable-CSample
   user-defined constructor code of CSample
}

This is why you have the vtable there.

There is a golden rule that calling a virtual function from a constructor directly or indirectly is a bad practice. Direct calls can be caught by the compiler, but indirect ones silently cause bugs and headaches. On indirect virtual function call I mean: you call a non-virtual function from the constructor and then that non-virtual function calls a virtual one. Why is this a problem? Lets say you call a virtual function from the constructor of C. When the constructor of C runs the vtable is initialized to the vtable of class C. This means that even if class D overrides the virtual function, the virtual function of C executes because we have only the vtable of C when constructor C runs!!! This causes a hard to find bug without crash!!! If you use the novtable with class C then the vtable is not initialized when constructor C runs so there are 3 possible scenarios:
1. The vtable pointer might be uninitialized because C and its base classes left it uninitialized so the virtual function call causes a crash.
2. One of the base classes of C doesn't have the novtable directive so it filled in the vtable. In this case if the vtable of this particular base class has an entry for the called virtual function then this virtual function will be executed (A), otherwise a crash occurs (B).
In my opinion a crash is always better and easier to find than unwanted behavior.

So, you can use novtable with any "abstract" class as an optimization. In case of novtable we can treat any classes "abstract" that won't be instantiated at runtime - for example we can use novtable relatively safely with a class whos constructor is has protected access modifier but care must be taken not to call a virtual function from the constructor directly or indirectly. Note that I worked on performance critical programs but I never reached a point where I started to use novtable to optimize. My humble opinion is that if your performance problems come from vtable initializations then you are doing something wrong. Performance problems are rather the consequences of algorithmic problems and cache-unfriendly memory access.

EDIT: you can't enforce interface rules with other mayor C++ compilers. Even if you define the __interface keyword to nothing with other compilers, you have to put there the virtual keyword for functions and either a dummy implementation or "= 0".
GeneralRe: __interface implies the novtable __declspec modifier Pin
bob1697210-Feb-13 6:03
bob1697210-Feb-13 6:03 
GeneralRe: __interface implies the novtable __declspec modifier Pin
pasztorpisti10-Feb-13 10:45
pasztorpisti10-Feb-13 10:45 
GeneralRe: __interface implies the novtable __declspec modifier Pin
bob1697210-Feb-13 19:22
bob1697210-Feb-13 19:22 
GeneralRe: __interface implies the novtable __declspec modifier Pin
H.Brydon11-Feb-13 15:45
professionalH.Brydon11-Feb-13 15:45 
GeneralRe: __interface implies the novtable __declspec modifier Pin
pasztorpisti12-Feb-13 4:53
pasztorpisti12-Feb-13 4:53 
QuestionAES Encryption Help Pin
vishalgpt7-Feb-13 23:21
vishalgpt7-Feb-13 23:21 
AnswerRe: AES Encryption Help Pin
Richard MacCutchan8-Feb-13 0:34
mveRichard MacCutchan8-Feb-13 0:34 
GeneralRe: AES Encryption Help Pin
vishalgpt8-Feb-13 2:55
vishalgpt8-Feb-13 2:55 
GeneralRe: AES Encryption Help Pin
Richard MacCutchan8-Feb-13 5:22
mveRichard MacCutchan8-Feb-13 5:22 
QuestionKernel programming Pin
OmarSH7-Feb-13 22:15
OmarSH7-Feb-13 22:15 
AnswerRe: Kernel programming Pin
Richard MacCutchan7-Feb-13 23:08
mveRichard MacCutchan7-Feb-13 23:08 
GeneralRe: Kernel programming Pin
OmarSH7-Feb-13 23:49
OmarSH7-Feb-13 23:49 
GeneralRe: Kernel programming Pin
Richard MacCutchan8-Feb-13 0:32
mveRichard MacCutchan8-Feb-13 0:32 
GeneralRe: Kernel programming Pin
OmarSH8-Feb-13 2:11
OmarSH8-Feb-13 2:11 
GeneralRe: Kernel programming Pin
Richard MacCutchan8-Feb-13 5:15
mveRichard MacCutchan8-Feb-13 5:15 
AnswerRe: Kernel programming Pin
Erudite_Eric8-Feb-13 0:09
Erudite_Eric8-Feb-13 0:09 
GeneralRe: Kernel programming Pin
Albert Holguin8-Feb-13 6:01
professionalAlbert Holguin8-Feb-13 6:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.