First, get your terms straight. C++ is a language, not an implementation. It doesn't impose a specific object model, and you can't "have it".

A simple C++ implementation could just store a pointer to the virtual base class' sub-object(s) in every derived class' object. Another approach is to store a pointer to a virtual base class table. Yet another one is to have the offset of each virtual base class in the virtual function table (usually having negative indices).

The book I mentioned contains explanations about the approaches I named.

If you'd like to inspect a few C++ compilers, there is a list in
Posted on 2005-03-07 18:34:48 by death
death, you're right - but I am just talking about VC++ (-compatible compilers) 's implementation. For me this is the most important x86 compiler, and if I were to start posting different implementations (after studying them ^^" ), it might become a mess. Most C++ SDKs are for VC anyway, and what other reason is there to talk about non-plugin implementations in asm, when studying C++'s internals ? Apart from searching for a way to port cpp classes to asm.
I haven't studied x86-gcc's output yet, but I get the feeling it has almost the same class object layout as VC's .

Maelstrom, I'm a bit tired and busy right now, I'll see about the virtual bases later. Though, I am 90% sure it's this sequence:
B overrides A's calls (in B's vTable)
C overrides A's calls (in C's vTable)
Remember, order matters. I assume you specify B first, and then C, when creating D.
C overrides B's calls (in D's vTable)
D overrides B and C's calls (in D's vTable)
The overrides happen only where you specify the same method name, as you know.
Yet, I am not sure whether both D's vTables are overwritten with the new function addresses (I suppose so). Actually I guess it must be that way (overwriting both vTable1 and vTable2), since when you do a
pcall d->FuncPresentInA() , there must be no collision - (making the compiler wonder which offset at which vTable to call).

Btw, there's a nice "Introductory edition" of VC++6.0 (which I use) - it's cheap ($20 including two books), and just its linker is a bit modified to make your exe display a copyright messagebox. It's great for education - just the thing I need from any C++ x86 compiler :-D
Posted on 2005-03-07 20:56:25 by Ultrano
Ultrano, there's also the free vc2003 toolkit, which is not brain-damaged in any way (ie, full optimizer), and has a license that allows you to do pretty much what you want to.
Posted on 2005-03-08 08:30:14 by f0dder
death, you're right - but I am just talking about VC++ (-compatible compilers) 's implementation.

I was referring to Maelstrom's use of the term. Although you also don't use correct terms :)

For example, "static methods". A method (an OOP term) is virtual by definition, so I took it you mean "static member function". However, static member functions don't have a 'this' pointer concept. Therefore I take it you mean non-virtual non-static (statically-bound) member functions.

Then I can understand what you mean by saying "while in C++ you usually define a static destructor". There is no such thing as "static destructors" in C++. Destructors always operate on a given object. Apart from that, I wouldn't say "usually". Perhaps you mean that you have non-virtual destructors by default.
Posted on 2005-03-08 13:38:42 by death
Hey guys

Yay, I finally get to read what was posted.

Sorry if I'm using the incorrect terms, I can see how it would create confusion to those who know what they're talking about.
I now realize that the language specification and implementation are two seperate entities.

Are my OOP definitions correct?

member data = exists in the class struct
member functions = statically bound function that recieves a 'this' ptr
static member data = statically bound data that exists in the data segment, not in the class struct
static member function = statically bound function that *doesn't* recieve a 'this' ptr
virtual member function = indirect function call using the virtual function table of the class

I downloaded the VC 2003 Toolkit and used it to output to asm. I must say I'm amazed at the amount of code generated to handle multiple inheritance.
I can see why you wouldn't want to use MI too much, the VC 2003 implementation must be a contender for the poster girl for bloat.
Surely MI can be handled more efficiently?
Posted on 2005-03-23 17:51:23 by Maelstrom
I was off for a while, so I get into this thread just now?
I have to say, that the terminology I used for ObjAsm32 is not the same as the used for the C++ OOP implementation since the approach is not the same.

Documentation can be found in the OA32 package, but basically, methods can be divided into 3 categories: static, dynamic and interfaces. The basic difference between these is where the method pointer is stored and handled.

About multiple inheritance, I think like Ultrano. The efforts you need to implement it are far beyond the usefulness. In my eyes, it is a property that falls in the category ?nice to have?. I don?t know any case where MI can?t be solved using another approach with single inheritance.


Posted on 2005-03-24 01:46:07 by Biterider
Are my OOP definitions correct?

The terms you mention are not OOP terms, but C++ terms. Here are the correct definitions for the terms you specified (AFAIK):

Data members - Objects declared inside the class definition. These may be static or non-static.
Member functions - Functions declared inside the class definition (that don't have the 'friend' specifier). These may be static or non-static. Non-static member functions may be virtual member functions. Your definition is correct only for non-static, non-virtual member functions.
Static data members - Data that is shared between all objects (per-class).
Static member function - A member function that can be invoked without an object, and therefore cannot directly use non-static member data.
Virtual member function (a.k.a. Methods in OOP terminology) - A dynamically-bound non-static member function (indirect function call).

Functions that are not virtual member functions are statically-bound.

I suppose if you want to exact definitions, you should look in the C++ standard.
Posted on 2005-03-24 12:21:05 by death
Hey guys

Thanks for the reply.
I'm beginning to think you and Ultrano are right. After seeing the code generated by VC 2003 to handle MI I don't think this feature warrents the extra complexity involved, escpecially if it's not going to be used a great deal. I'll keep playing around with it and see what I can achieve.

Thanks for the clarification.
Posted on 2005-03-24 15:41:33 by Maelstrom

The terms you mention are not OOP terms, but C++ terms.
I suppose if you want to exact definitions, you should look in the C++ standard.

:shock: Am I just tired, or is the last sentence negating the first.
Anyway, nevermind that.

I looked at SmallTalk, the "almighty real OOP". I thought there's nothing worse than Java. I am an asm coder, so "bad" also means to me "slow" or "too far away from cpu", when referring to code.
I now divide OOP in three categories:
- "real" OOP (and actually useless to us asm coders) of SmallTalk.
- "half-real" OOP of C++ . (Because of the class::operator)
- "asm" OOP. The syntaxes NaN, Biterider and I thought so much on, in order to perfectly balance speed, size and power. While being pushed back by the limits and lack of complete documentation of masm's macros. During our work on these frameworks, we saw which features are useless to implement, and made sure the features where (usability*1000>=effort) are present and easy to use.

So, death, please respect my wish to stop b*tch*ng about "correct terms". Not all of us have read the books you have read, or in your language. I myself learnt oop through: 1)A Bulgarian book about MFC 2)x86 disassembly 3)trying to find the best way to make reusable objects, with fewest possible cache-misses on accessing vTables.
Half of your OOP posts are about incorrect terms we use, if you haven't noticed.
Posted on 2005-03-24 17:21:13 by Ultrano

The terms you mention are not OOP terms, but C++ terms.
I suppose if you want to exact definitions, you should look in the C++ standard.

:shock: Am I just tired, or is the last sentence negating the first.

I was referring to the definitions I gave, which came from my memory.

So, death, please respect my wish to stop b*tch*ng about "correct terms".

No problem.
Posted on 2005-03-24 20:10:16 by death
I would recommend implementing multiple inheritance in a manner that is similar to the way the Ruby scripting language does it.  The method taken by ruby is to simulate multiple inheritance with what it has termed Mixins.  The way that it works is to make it so classes can only directly inherit from one base class, but they can have zero or more mixins.  This produces linear inheritance rather than a tree-like inheritance that you see in C++.  It solves the problems you run into with ambiguity and doesn't have any side effects (that I've observed).  You can read more about it here:

(I skimmed through the other posts and saw that no one else had commented on this, so hopefully it's relevant)
Posted on 2005-08-14 10:36:40 by nohaven
Hi nohaven
Some time ago we discussed this topic and decided to go in direction of "single inheritance", but if there is a simple way to implement something like "multiple inheritance", I?m willing to see it in detail.

Are you familiar with Ruby?s Mixins? I?m not, but from the shown examples, it seems to be something like a MASM macro that expands into the class definition. Maybe I?m wrong. Perhaps a better explanation on how it works would be helpful.  ;)


Posted on 2005-08-14 16:00:51 by Biterider
Hi guys,
Few weeks ago i have strange but interesting problem with multiple inheritance in .Net (Java is almost the same, i think everybody know Java),
I have one class person (P to make easier) and one class company (C), both of them can be clients (L), but person can also be employee (E), so:

| |\

All clients have some comum methods, and my store receive a C to execute actions like buying, a person buy things in a diferent way from companies so the implementation of those methods are diferent, in .Net (and also Java) the easiest way to do it is using an interface client,
Now begin the problem, the ID from a person and a company are generated in diferent ways, but i validate it in the same way, in a interface i must implement the validation twice (in P and C) or create a static method to do it (very ugly),
so why not implement this static method as a final method in the interface?
It's not hard to do, the code and the binary stay exactly the same, only the logic changes:

interface client
int id;
bool valid() //final method
class person
class pc : person, client
int id{...}
class company : client
int id{...}
class employee : person
Posted on 2006-03-18 10:41:36 by Eduardo Schardong