Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C++ class inheritance question

  1. Jul 31, 2011 #1

    uart

    User Avatar
    Science Advisor

    I just came across another question while brushing up on my c++.

    If you have a base class that uses virtual methods, when you try to use it to define a derived class then you *need* to prefix the base class name with "public", as in the following example.

    Code (Text):
    class ExampleBaseClass {
        ...
        virtual void ExamlpeVirtualMemberFunction();
        ...
    }

    class ExampleDerivedClass: >>>>PUBLIC<<<< ExampleBaseClass {
        void ExampleVirtualMemberFunction();    //overrides base class
    }
    Ok ignore the ">>><<<" and the capitals, it is of course just a plain lower case "public", I just wanted to highlight it so readers could easily see what I was referring to.

    We do we need that?
     
  2. jcsd
  3. Jul 31, 2011 #2

    I like Serena

    User Avatar
    Homework Helper

    Your PUBLIC is not required, although it is customary.
    It makes the public and protected methods in the base class visible outside the derived class.
    If you would leave it out, or substitute "private", you would effectively hide all methods in the base class to any user of the derived class.
    This is a bit weird though, because if you cast a pointer to the derived class to a pointer of the base class, the methods are visible again.

    So the recommendation is to always put "public" where you wrote PUBLIC.
     
  4. Jul 31, 2011 #3

    uart

    User Avatar
    Science Advisor

    No that's not correct. I'm using gcc and even the most simple example that I can make will not compile unless the "public" prefix is used as outlined above. It's definitely not optional.

    Secondly, I have tested this and the public prefix (in the context given above) makes absolutely no difference to the visibility (public private) of either the base class or the derived class, (they remain exactly as I specified them within their class definitions in each case).

    So the question remains open. Though I am kind of expecting that I wont find any answer other than "that's just the way it is".
     
  5. Aug 1, 2011 #4

    I like Serena

    User Avatar
    Homework Helper

    All right, I've just tried it as well (gcc version 4.4.3).
    I left out the "public" prefix and had no problem...
    So what did you do?

    I did find that casting the derived class to the base class gives:
    error: ‘ExampleBaseClass’ is an inaccessible base of ‘ExampleDerivedClass’

    For reference, here's my code:
    Code (Text):
    #include <iostream>

    class ExampleBaseClass {
    public:
        virtual void ExampleVirtualMemberFunction() { std::cout << "Base::ExampleVirtualMemberFunction" << std::endl; }
        virtual void ExamplePublicBaseMemberFunction() { std::cout << "Base::ExamplePublicBaseMemberFunction" << std::endl; }
    };

    class ExampleDerivedClass: ExampleBaseClass {
    public:
        void ExampleVirtualMemberFunction()    //overrides base class
        { std::cout << "Derived::ExampleVirtualMemberFunction" << std::endl; }
    };

    int main(void)
    {
        ExampleDerivedClass d;
        ExampleBaseClass b;
       
        d.ExampleVirtualMemberFunction();
        b.ExampleVirtualMemberFunction();
        b.ExamplePublicBaseMemberFunction();
       
        return 0;
    }
     
     
  6. Aug 1, 2011 #5
    Close, but not exactly. The public/protected/private specifies the most visible the inherited members can be.

    For example:

    Code (Text):
    class base
    {
    public:
        void member1();
    private:
        void member2();
    };

    class derived1 : public base{}; // inherits member1() as public and member2() as private
    class derived2 : protected base{}; // inherits member1() as protected and member2() as private
     
  7. Aug 1, 2011 #6

    uart

    User Avatar
    Science Advisor

    Ok thanks guys. :smile:

    Looking at the above code I've figured out that the difference in my case is that I'm also inheriting some member data as well. When I remove all reference to the inherited data then yeah it will compile without error.

    BTW. I'm not trying to access the class data directly. It's only accessed via member functions, so I really don't see why public is necessary. Surely if a class inherits data then it should be able to access it's own data, regardless of whether it's private or public!
     
  8. Aug 1, 2011 #7

    uart

    User Avatar
    Science Advisor

    Ok here's some simple code to illustrate what I've found.
    Code (Text):
    #include <cstdlib>
    #include <iostream>
    using namespace std;

    class Pet {
            float FeedCostPerWeek;
            string Name,Colour;
          public :
            void InitP(string Name, string Colour, float cost);
            virtual void MakesNoise() {cout << "I'm only a virtual pet, I don't make a noise." << endl;}
    };

    void Pet::InitP(string nam, string col, float c) {
         Name = nam;
         Colour = col;
         FeedCostPerWeek = c;
    };

    class Dog: Pet {
           public :
            void MakesNoise() {  
            cout << "Ruff - Ruff" << endl;
            }
    };      

    int main(void) {
        Dog  MyDog;
    //    MyDog.InitP("Fido", "Brown", 10.0);
        MyDog.MakesNoise();
        return 0;                                            
    }
    This compiles ok as long as the call to "MyDogInitP" in main is commented out (as shown above). As soon as I put that line back however it fails to compile and tells me that "InitP is inaccessible".
     
  9. Aug 1, 2011 #8
    That's because when no access level is specified, the compiler assumes private. Which means that InitP is inherited as a private member. You can fix it by putting "public" there.

    I think you would benefit greatly from reading the "Inheritance between classes" paragraph, here: http://www.cplusplus.com/doc/tutorial/inheritance/.

    Also, IMHO, your design is flawed. I would do it like this:

    Code (Text):
    #include <cstdlib>
    #include <iostream>
    using namespace std;

    class Pet {
            float FeedCostPerWeek;
            string Name,Colour;
          public :
            Pet(string Name, string Colour, float cost);
            virtual void MakesNoise() = 0 // If it's abstract(no instances, just derived classes) make the method abstract. The = 0 makes it abstract. A class with an abstract member cannot be instantiated, but its derived classes can, as long as they override the abstract method.)
    };

    Pet::Pet(string nam, string col, float c) {
         Name = nam;
         Colour = col;
         FeedCostPerWeek = c;
    };

    class Dog : public Pet {
           public :
            Dog(string Name, string Colour, float cost) /****/: Pet(string Name, string Colour, float cost)/****/ {}
            void MakesNoise() {  
            cout << "Ruff - Ruff" << endl;
            }
    };      

    int main(void) {
        Dog  MyDog("Fido", "Brown", 10.0);
        MyDog.MakesNoise();
        return 0;                                            
    }
    Note: the thing enclosed in /****/'s is called an initialization list.
     
    Last edited by a moderator: Apr 26, 2017
  10. Aug 1, 2011 #9

    uart

    User Avatar
    Science Advisor

    Thanks for the info and the link TylerH.
    That code wasn't meant to be taken too seriously as it was just the shortest piece I could think of to illustrate my issue. It was "snipped" from larger program in which I did "instantiate" the base class. It was part of a simple program to illustrate the results of using, or not using, virtual methods (to demonstrate the difference between compile time binding versus late binding).

    The code was translated from an earlier example that I'd written many years ago in Delphi for the same educational purpose. Don't take that little code snippet out of context. :smile: BTW. I'm pretty fluent in Pascal Delphi, but am just trying to familiarize myself with the equivalent concepts in c++ at the moment.
     
    Last edited: Aug 1, 2011
  11. Aug 1, 2011 #10

    I like Serena

    User Avatar
    Homework Helper

    FYI.

    I use the HICPP coding guidelines in my work.
    Here's the one about public derivation and the justification why you should always use "public" in derivations.
    It is borrowed from Scott Meyer's "Effective C++", which is one of the international standards on good practice C++ coding.


    High Integrity CPP Rule 3.3.1 Use public derivation only. (QACPP 2193, 2194)

    Justification
    Using public derivation maintains visibility of public base members in an intuitive way. Public derivation indicates the "is-a" relationship. Private derivation indicates the "is-implemented-by" relationship, which can also be indicated by containment (that is, declaring a private member of that class type instead of inheriting from it). Containment is the preferred method for "is-implemented-by", as this leaves inheritance to mean "is-a" in all cases.

    Code (Text):
    class A {};
    class B : private A {}; // avoid private derivation
    class C : protected A {}; // avoid protected derivation
    class D : A {}; // avoid implicitly private derivation
    class E : public A {}; // prefer public derivation
    Reference Effective C++ Item 42;
     
  12. Aug 1, 2011 #11

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    While the derived class can do this cast, the public at large (pun intended) cannot. The inheritance itself is hidden.


    It does more than that. The inheritance from BaseClass to DerivedClass (for example) is itself hidden if the inheritance is not public.

    One way to look at it: Public inheritance is an "is-a" relationship. Private inheritance is a "is implemented as-a" relationship. In particular, it is not "is-a".


    ---------------------------------------------------

    So why use non-public inheritance? While protected inheritance is a bit flaky, private inheritance has found a number of uses in the C++ world. Just a couple:

    1. You want to expose part of, but not all of, the base class' public functionality. For example, several of the base class methods just don't make sense in the context of your class. Private inheritance is one way to accomplish this. (Composition rather than inheritance is oftentimes another way to accomplish this.)

    2. Java has final classes. C++ doesn't. Except it does.
    Code (Text):
    class Final;

    class FinalMixin {
    private:
       friend class Final;
       FinalMixin() {}
       virtual ~FinalMixin() {}
    };

    class Final : private virtual FinalMixin {
    public:
       Final() {}
       virtual ~Final() {}
    };
     
    The class Final is a final class in the sense of Java. There is no way to inherit from it. In the upcoming standard, the above FinalMixin class can be templatized and used with the curiously recurring template pattern to form a true C++ mixin:
    Code (Text):
    template <typename T>
    class FinalMixin {
    private:
       friend T;
       FinalMixin() {}
       virtual ~FinalMixin() {}
    };

    class Final : private virtual FinalMixin<Final> {
    public:
       Final() {}
       virtual ~Final() {}
    };
     
     
  13. Aug 1, 2011 #12

    uart

    User Avatar
    Science Advisor

    Ok thanks very much ILS and TylerH. Together I think you've cleared up my issue now. :)
     
  14. Aug 1, 2011 #13

    uart

    User Avatar
    Science Advisor

    Yes this is getting at what I was finding confusing. I thought that the whole point of using a derived class was to get inheritance, so to by default make that inheritance hidden (which to my simple level of understanding seemed to make it unusable) seemed a strange thing for c++ to do.

    Now I see that this is a least partly due to my inability to imagine any situations where hiding the inheritance would be useful.
     
  15. Aug 1, 2011 #14

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    One way to think of it is that public inheritance is a "is-a" relationship, while protected/private inheritance is a "is-implemented-by" relationship.

    You may well never find a use for non-public inheritance. It isn't very common, and some look down on it.
     
  16. Aug 1, 2011 #15
    Oh, okay. I did think it was weird for a frequent contributor to the CS section to mess that up, I didn't consider the fact it was an example.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: C++ class inheritance question
  1. C++ operator classes (Replies: 9)

Loading...