News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Pet peeve #1

Started by shankle, December 12, 2012, 12:02:25 AM

Previous topic - Next topic

CommonTater

Quote from: Gunther on December 16, 2012, 12:26:41 AM
Hi qword,

Quote from: qWord on December 12, 2012, 09:20:46 AM
No, it is the beautiful C  :t

C with classes? You're kidding.

Gunther

You can do object oriented programmin in C (eg. COM Objects) ... but why on earth would you want to?

There's a huge difference between a struct named "Class" and an actual C++ Class ....

qWord

CommonTater ,
can you please explain a bit more detailed what you mean with "must" and "can"? I'm sure you can create a c++ class without a virtual table , unless using virtual functions (also, AFAIK the vtbl is implementation specific and not part of the standard) .

qWord
MREAL macros - when you need floating point arithmetic while assembling!

CommonTater

Quote from: qWord on December 16, 2012, 08:09:12 AM
CommonTater ,
can you please explain a bit more detailed what you mean with "must" and "can"? I'm sure you can create a c++ class without a virtual table , unless using virtual functions (also, AFAIK the vtbl is implementation specific and not part of the standard) .

C++ methods are accessed by a virtual table (a struct of pointers) inside the class.  It's also the key to inheritance in classes as the new class inherits (copies) the vtable from it's parent...

The vtable is hidden from the programmer in C++ but C calls class functions as class->vtable->method() so we can see it.

Trust me, it's there... always.



qWord

Quote from: CommonTater on December 16, 2012, 10:26:38 AMC++ methods are accessed by a virtual table (a struct of pointers) inside the class.  It's also the key to inheritance in classes as the new class inherits (copies) the vtable from it's parent...
This is also my understanding of classes with virtual methods. I can't though why any compiler should add a non-virtual metode to the vtable.
MREAL macros - when you need floating point arithmetic while assembling!

qWord

let me describe my thoughts in other words:
If you create a class in C++ which does not contain virtual functions, everything the compiler needs to known (for all modules) is the structure/class definition. The methods then are simply called by their name (e.g. Class::methode@Signature) and the linker does the fix up. The other members are referenced by the corresponding structure pointer (this-pointer). Because no function pointers are used in the structure definition, derived classes must overwrite/hide the methods by redeclaring the same function (this must be supported by the language and is thus not possible with C in that way).

For classes with virtual methods, the class template get be copied and the constructor* then fix up the virtual method pointers of the base class (in the vtable). The virtual methods then can be called either by the base class or by the derived classes. The overwritten virtual methods of the base class can still be called through the template of the base class (unless the class is not abstract).
I'm right here?

regards, qWord

* if it is a derived class
MREAL macros - when you need floating point arithmetic while assembling!

CommonTater

Quote from: qWord on December 16, 2012, 10:40:56 AM
Quote from: CommonTater on December 16, 2012, 10:26:38 AMC++ methods are accessed by a virtual table (a struct of pointers) inside the class.  It's also the key to inheritance in classes as the new class inherits (copies) the vtable from it's parent...
This is also my understanding of classes with virtual methods. I can't though why any compiler should add a non-virtual metode to the vtable.

The vtable is a struct of pointers to methods ... rather than have 5 identical copies of every method in memory at the same time (a la Delphi) the vtables all point to the first copy.

It has *nothing* to do with virtual vs real methods.

What is in the actual class struct itself is the class's data.

qWord

Quote from: CommonTater on December 16, 2012, 12:34:28 PM
Quote from: qWord on December 16, 2012, 10:40:56 AM
Quote from: CommonTater on December 16, 2012, 10:26:38 AMC++ methods are accessed by a virtual table (a struct of pointers) inside the class.  It's also the key to inheritance in classes as the new class inherits (copies) the vtable from it's parent...
This is also my understanding of classes with virtual methods. I can't though why any compiler should add a non-virtual metode to the vtable.

The vtable is a struct of pointers to methods ... rather than have 5 identical copies of every method in memory at the same time (a la Delphi) the vtables all point to the first copy.

It has *nothing* to do with virtual vs real methods.

What is in the actual class struct itself is the class's data.
You say: a class has always a vtable because inheritance requires it
My opinion: a vtable is only need if virtual function are used, because these requires fix up at runtime. None-virtual function are known at compile time thus they can be called by their symbol.

Anyone else can assistance?

regards qWord
MREAL macros - when you need floating point arithmetic while assembling!

CommonTater

Quote from: qWord on December 16, 2012, 11:34:50 AM
let me describe my thoughts in other words:
If you create a class in C++ which does not contain virtual functions, everything the compiler needs to known (for all modules) is the structure/class definition. The methods then are simply called by their name (e.g. Class::methode@Signature) and the linker does the fix up.

Not exactly.  If it were done that way you could not replace a method in a derived class and you'd end up with multiple copies of the method code, one in each instance of the class.

In C and C++ a function's name is a pointer to the function's entry point... a variable like any other. 

When a class or object is created, these pointers are concentrated in the class's vtable.  The only place the method is called by name is in source code.

Quote
The other members are referenced by the corresponding structure pointer (this-pointer). Because no function pointers are used in the structure definition, derived classes must overwrite/hide the methods by redeclaring the same function (this must be supported by the language and is thus not possible with C in that way).

Function pointers are *hidden*... in C++ the vtable is hidden from the programmer... but a pointer to a vtable is always there.

This has nothing to do with virtual methods.

Quote
For classes with virtual methods, the class template get be copied and the constructor* then fix up the virtual method pointers of the base class (in the vtable). The virtual methods then can be called either by the base class or by the derived classes. The overwritten virtual methods of the base class can still be called through the template of the base class (unless the class is not abstract).
I'm right here?

Yes and no... You have the concept, but not the mechanics of it...

The root or base class has a pointer to a vtable (similar to an ASM jump list) that points to it's methods, including the constructor and destructor.  When an inherited (or derived) class is instantiated, it's vtable pointer simply points to it's parent's vtable... No matter how many derived classes you make, there is only one copy of the vtable and one copy of each method in memory, unless you are replacing methods.  If you overlay (replace) one or more methods in a derived class, then the derived class gets it's own copy of the vtable, with the new pointer(s) in it.

Here's what a C++ class (IExample) looks like in C...

typedef struct {
   IExampleVtbl * lpVtbl;
   DWORD          count;
   char           buffer[80];
} IExample;


C++ hides the IExamplevtbl entry from the programmer and does tricks to make it look like it has it's own copy of the parent's methods ... but the vtable is there. 

The vtable pointer is always the first entry in the struct (and thus at the same address as the struct itself). It points to a list of the addresses of the methods used in the class. If we make a second copy we can simply copy the first under a new name, call the constructor (always the first item in the Vtable) and use it with different data.

In C...

IExample test;  // declaration of an instance

test->IExampleVtbl->IExample;  // run the constructor

test->IExampleVtbl->copy(string);  // run a method


In C++...

IExample test;  // instance, constructor is run automatically

test::copy(string);


Both of the above do the same thing... it's just that in C++ it's hidden from you.


qWord

thx for your answer.
In the mean time I've done some test with VC++  and it seem like that it confirmed my assumption about the vtable that is not created for classes without virtual function. However, I will stay in tomorrow more deeply and report here.

regards, qWord
MREAL macros - when you need floating point arithmetic while assembling!

qWord

Quote from: CommonTater on December 16, 2012, 01:35:42 PMNot exactly.  If it were done that way you could not replace a method in a derived class and you'd end up with multiple copies of the method code, one in each instance of the class.
Why should the code be copied?

Quote from: CommonTater on December 16, 2012, 01:35:42 PMbut a pointer to a vtable is always there.
No, it is not always there - just test it. The quick test I've made (VC++) shows that it is done that way I've described in my previous posts.
Furthermore, if you search with your favorite search engine, you will quickly find several articles and discussions that confirm my assumptions.

regards, qWord
MREAL macros - when you need floating point arithmetic while assembling!

Tedd

In C++ the vtable is only required when virtual methods are present.
Some strange compilers may choose to add it in anyway, but it's not general practice.
Java, on the other hand, always has a vtable because all methods are virtual.

Code doesn't need to be copied, non-virtual methods are called directly since their address is known at compile time.
While virtual methods could have been replaced, so they must be called via a pointer - in the vtable.
The vptr is always present -- to simplify member offsets (no need to check whether there's a vtable before accessing a member) and to ensure no object can be zero bytes in length (each object must have a unique address) -- but doesn't point to a vtable if the class doesn't require one.

The usual layout for an object in memory is: { vptr, member_variables..., vtable_pointers_if_present... }
Having only a single copy of the vtable for any particular class is a possibility, but it falls down when you introduce multiple inheritance.
Potato2