Multiple Inheritance - Size of Classes?

This is a discussion on Multiple Inheritance - Size of Classes? within the C++ Programming forums, part of the General Programming Boards category; Well let me start off with background, I am reading a book (learn C++ in 21 days by Sams Publishing), ...

  1. #1
    #junkie
    Join Date
    Oct 2004
    Posts
    240

    Multiple Inheritance - Size of Classes?

    Well let me start off with background, I am reading a book (learn C++ in 21 days by Sams Publishing), and I am having a couple of questions.

    It seems they are basically saying that classes are designed to do one thing very well, many classes each of which doing one thing well is good coding practice. Now that is not my main question so don’t bother arguing semantics about the situation or anything lol.

    What I want to know is more specifically referring to Multiple Inheritance. It uses a great example of Animal, Mammal, ect. Classes. Such as..
    Code:
     Animal		 Animal
          |		      |
     Horse		   Bird
          |		      |
           ----------------------
    	      |
    	Pegasus
    (lol ok the ascii art isnt working, if someone knows a way pleas enlighten me lol. But Animal is on top, Horse is under animal, Bird is also under Animal but aparently they have nothing to do with eachother. Then Pegasus uses multiple inheritance to use both Bird and Horse).

    Now forgive my lack of ASCII code talent, but apparently each of those are classes. An Animal, Horse, Bird, and Pegasus class. Of course bird was matched with mammal at first, but for this example its not.

    Now to make Pegasus fly, and gallop, you use multiple inheritance,
    Code:
    class Pegasus : public Horse, public Bird {
    }
    To allow him to do both.

    My question is that if you do that, in bigger situations are you not wasting memory space by allocating unneeded Methods? Or does C++ when using inheritance only allocate memory that of which is being called by the calling class.
    Such as if Bird has methods “Fly();” and “Chirp();”, and Pegasus uses inheritance to be able to use Fly(); from the class Bird, does C++ also allocate memory for Chirp();?

    Because my understanding of classes is that when you load a class the amount of memory being allocated for each class is the sum of all its methods, be it data or function. For example so many 8byte variables add up into one memory address for the class.

    Now I was just curious if it is better coding practice due to less memory being used, however not as easy to debug, if you separate each classes functions if it would seem wasteful.
    Like if Bird had say 20 methods, and Pegasus only needed one of those methods, Fly();.

    Anyway, I hope you understand my question, thanks for reading
    01110111011000010110110001100100011011110010000001 11000101110101011010010111010000100000011011000110 10010110011001100101001000000111100101101111011101 0100100000011011100111010101100010

  2. #2
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    I am reading a book (learn C++ in 21 days by Sams Publishing)
    Burn it

    But to your question: It depends a lot on the compiler and the linker. Through some testing I have found that g++ will compile all the functions (exception being templates) but will only link what it needs. So if you never use Chirp() it won't be linked in the final app.

    I would imagine that any reasonable compiler will do the same.

    Now for the sizeof() part with g++ it was the sum of the sizeof the data members and the sizeof a pointer for each virtual function.

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Each method exists exactly once in my memory. It is the this pointer's responsibility to make sure the distinction between objects and classes remains clear, as far as that is necessary.

    In other words, Pegasus and Bird share their Fly() method if Pegasus inherits it.

    You have one misunderstanding of terms: method only refers to member functions, never to data (member variables).

    Now I was just curious if it is better coding practice due to less memory being used, however not as easy to debug, if you separate each classes functions if it would seem wasteful.
    It would be better coding practice, but not for the reason you gave.
    The real reason is about object-oriented design. Inheriting as public means "is-a". This is the simplest and most common definition. There's a more technical definition, known as the subtype relation. This definition essentially says that a class should derive another as public if, and only if, it can be substituted in every situation where the parent class might be used.
    This implies that every single method of the parent class must have a well-defined meaning in the subclass. If your Bird can chirp(), but the Pegasus can not, then Pegasus must not derive from Bird. If chirping is a universal skill of Bird, and Pegasus can't chirp, then obviously Pegasus isn't a bird.
    My current professors at the university are very strict about it. One interesting part is that it does not allow for restriction. Example: since birds can fly, the Bird class has the fly() method. What about the Penguing? You might say, "A Penguin is-a Bird that can't fly." As good as it sounds, from an engineering stand point it's nonsense. Things are defined by what they can do, not by what they can't. (Now that's a sentence I like.) So you'd have to split Bird into the functionality common to all birds, even those that can't fly (quite a lot), and those that can fly, introducing another abstract class FlyingBird.

    Enough rambling.

    ETA:
    Now for the sizeof() part with g++ it was the sum of the sizeof the data members and the sizeof a pointer for each virtual function.
    I can't believe that. gcc has a very similar binary layout as VC++, which means that in a simple hierarchy (without virtual or multiple inheritance) the size of a class is the sum of its data members and possible padding, and one pointer if there is a vtable (at least one virtual method). The vtable gets one more pointer for each virtual function, though, and possibly even more data if RTTI is enabled - but neither is per-instance data.
    Last edited by CornedBee; 11-25-2004 at 02:35 PM.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    using test code of:
    Code:
    #include <iostream>
    class A
    {
      int x;
      public:
        A() {}
        void a_print() {}
    };
    class B
    {
      int y;
      public:
        B() {}
        void b_print() {}
    };
    class C : public A
    {
      int x;
      public:
        C() {}
        void c_print() {}
    };
    class D : public B
    {
      int x;
      public:
        D() {}
        void d_print() {}
    };
    
    class E: public C, public D
    {
      int x;
      public:
        E() {}
        void e_print() {}
    };
    int main()
    {
      std::cout<<"A: " << sizeof(A) << '\n'
               <<"B: " << sizeof(B) << '\n'
               <<"C: " << sizeof(C) << '\n'
               <<"D: " << sizeof(D) << '\n'
               <<"E: " << sizeof(E) << std::endl;
    }
    As is:
    Code:
    A: 4
    B: 4
    C: 8
    D: 8
    E: 20
    Making a_print() virtual:
    Code:
    A: 8
    B: 4
    C: 12
    D: 8
    E: 24
    Making b_print() virtual (2 total virtuals):
    Code:
    A: 8
    B: 8
    C: 12
    D: 12
    E: 28
    Making c_print() virtual (3 total virtuals):
    Code:
    A: 8
    B: 8
    C: 12
    D: 12
    E: 28
    making d_print() virtual (4 total virtuals):
    Code:
    A: 8
    B: 8
    C: 12
    D: 12
    E: 28
    making e_print() virtual (5 total virtuals):
    Code:
    A: 8
    B: 8
    C: 12
    D: 12
    E: 28
    It appears I was mostly incorrect. My statement above was based off of observation without doing a lot of indepth looking.

  5. #5
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    The major issue I have with C++ design is that it does incur an awful lot of function call overhead. Be extremely careful how many virtual functions you create in your classes because each time you are incurring this overhead.

    I've run into this in my video game programming efforts and found that non-virtual functions are best from a speed standpoint but not so nice from an object-oriented approach. However in my game engine I have very strict rules that each class must meet if it is going to be derived from another class. The explanation that Corned Bee gave is a very good example of the thought process you should go through before you start deriving ten thousand classes from ten thousand bases.

    The C++ class is a powerful beast but it does carry around a substantial amount of overhead depending on how you structure it and how you use it. Remember...no matter what each function call is overhead. Each copy of a structure to another is overhead. For instance this code killed my laser system when I ran it. I had a matrix structure in my class and created a local matrix in the create function. Copying the local copy to the class copy lagged the entire system. Even if I copied it line by line it was still slower than crapola. So I just performed the operations on the matrix in the class instead of using a local and then copying.

    Just make sure you understand what is going on, or have a good idea of what is going on, under the hood when you create your classes and when you use them. The assembly output is the best indicator of what is taking place...if you know assembly. Some of my code has been completely restructured and looks a bit odd from a C++ standpoint simply because the assembly output was...well....hideous when I had it coded the other way.

  6. #6
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    The major issue I have with C++ design is that it does incur an awful lot of function call overhead. Be extremely careful how many virtual functions you create in your classes because each time you are incurring this overhead.
    But you're only talking the dereference of a pointer along with function call overhead, which is insignificant unless if the method function fairly small anyway. Often these type of small virtual methods may be reduced to inline methods. For example, the CanFly in the first class may be reduced to the class following.

    Code:
    class Bird {
    public:
             virtual bool CanFly() const = 0;
    };
    
    class Bird2 {
    public:
          Bird2(bool fly) : canFly(fly) { }
          bool GetCanFly() const { return canFly; }
    private:
          bool canFly;
    };
    To the client, the classes using this Bird class, the behavior is almost identical. Only the class inheriting from bird will have to change.

    From my standpoint, the two classes are almost identical in terms of design. Allowing derived classes to override "GetCanFly" allows for some complicated processing inside the method, at least more complicated then simply returning a variable. But nothing is truly gained by this extra behavior: either a bird flies or it don't.

  7. #7
    #junkie
    Join Date
    Oct 2004
    Posts
    240
    Wow, lots of posts lol. Thanks for the great response all , i assure you i will read em im just busy atm, thanks giving and all
    01110111011000010110110001100100011011110010000001 11000101110101011010010111010000100000011011000110 10010110011001100101001000000111100101101111011101 0100100000011011100111010101100010

  8. #8
    #junkie
    Join Date
    Oct 2004
    Posts
    240
    Btw Thantos, the book "Learn C++ in 21 Days", published by Sams is an awesome book for beginners. I admit i dislike the type of books that this is, a 21 days, week, and ect.. type of book. But none the less for a complete beginner (n00b) to C++, This book is awesome. I sat and rough read many books, including many that were suggested at a bookstore. This is by far the one i liked the most.

    I still like it. . It has good examples heavily throughout the book, shows good source code, and has a good set of dif type of quizes at the end of every chapter(day).

    Any minor reason you have no "burn" this book is in my opinion heavily outweighed by the usefulness to a beginner in the c++ field. Iv been told sams dont explain, have things wrong, ect. As far as dont explain, so far, assuming iv read, This book has explained almost everything it tries to in well detail. As for things wrong, well it may be a minor thing here and there but i wouldent know. None the less with my C++ friends and whatnot, in kind of review sessions (friends who know c++, not nubs like me lol), i have yet to see the book have anything wrong.

    So unless you read this book in whole yourself, then i'll take your opinion to "burn" it and use my own opinion to not burn it, however if you have not read it please dont throw over useless bashing on a book you have not read. I have seen many people in discussing this book love it, and say exactly what i have, that it explains well, and so on.

    Anyway, sorry but i just wanted to set that straight, thanks for your help and everyone elses
    01110111011000010110110001100100011011110010000001 11000101110101011010010111010000100000011011000110 10010110011001100101001000000111100101101111011101 0100100000011011100111010101100010

  9. #9
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Do a board search on that book and you'll see the reasons I say to burn it.

  10. #10
    #junkie
    Join Date
    Oct 2004
    Posts
    240
    i have before i bought it, and overall i wasent going to read the prob 100 pages of crap to find the small little bit relevant to my topic at hand lol. I found a little here and a little there, but have you read it?

    All i know is i read it, i know some others who have as well, and we love it for the reasons i said.
    01110111011000010110110001100100011011110010000001 11000101110101011010010111010000100000011011000110 10010110011001100101001000000111100101101111011101 0100100000011011100111010101100010

  11. #11
    Registered User
    Join Date
    Nov 2003
    Posts
    53
    I am also a relative newbie to C++ and have also read that book...I agree with Zeusbwr it is quite a good book. It explains things quite well for people who havent programmed before and so far I havent found any directly wrong information in it (just as a side note - that doesnt go for all of the "Sams" books, I have read others there were...well...plain bad and didnt explain anything at all)
    Its all a matter of willpower

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. references and multiple inheritance - incompatible?
    By m37h0d in forum C++ Programming
    Replies: 11
    Last Post: 09-03-2008, 02:35 PM
  2. Defining multiple classes in the same header file
    By Stonehambey in forum C++ Programming
    Replies: 2
    Last Post: 08-14-2008, 10:36 AM
  3. Invalid conversion from 'void*' to 'BYTE' help
    By bikr692002 in forum C++ Programming
    Replies: 9
    Last Post: 02-22-2006, 10:27 AM
  4. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM
  5. Multiple virtual inheritance
    By kitten in forum C++ Programming
    Replies: 3
    Last Post: 08-10-2001, 10:04 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21