C++ class inheritance question

  • C/C++
  • Thread starter uart
  • Start date
  • Tags
    C++ Class
In summary: Pet(int number); void feed(); };class Cat { ... public: Cat(int number); void feed(); };int main(){ Pet p1(5); Pet p2(10); cout << "p1 has " << p1.number << " pet and p2 has " << p2.number << " pet" << endl; cout << "feeding p1 will cost " << p1.feed() <<
  • #1
uart
Science Advisor
2,795
21
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:
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?
 
Technology news on Phys.org
  • #2
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.
 
  • #3
I like Serena said:
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.

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 won't find any answer other than "that's just the way it is".
 
  • #4
uart said:
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 won't find any answer other than "that's just the way it is".

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:
#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;
}
 
  • #5
I like Serena said:
It makes the public and protected methods in the base class visible outside the derived class.

Close, but not exactly. The public/protected/private specifies the most visible the inherited members can be.

For example:

Code:
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
 
  • #6
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!
 
  • #7
Ok here's some simple code to illustrate what I've found.
Code:
#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".
 
  • #8
uart said:
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".
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:
#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:
  • #9
Thanks for the info and the link TylerH.
TylerH said:
Also, IMHO, your design is flawed. I would do it like this:
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:
  • #10
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:
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;
 
  • #11
I like Serena said:
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.
While the derived class can do this cast, the public at large (pun intended) cannot. The inheritance itself is hidden.


TylerH said:
Close, but not exactly. The public/protected/private specifies the most visible the inherited members can be.
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:
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:
template <typename T>
class FinalMixin {
private:
   friend T;
   FinalMixin() {}
   virtual ~FinalMixin() {}
};

class Final : private virtual FinalMixin<Final> {
public:
   Final() {}
   virtual ~Final() {}
};
 
  • #12
Ok thanks very much ILS and TylerH. Together I think you've cleared up my issue now. :)
 
  • #13
D H said:
It does more than that. The inheritance from BaseClass to DerivedClass (for example) is itself hidden if the inheritance is not public.

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.
 
  • #14
uart said:
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.
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.

Now I see that this is a least partly due to my inability to imagine any situations where hiding the inheritance would be useful.
You may well never find a use for non-public inheritance. It isn't very common, and some look down on it.
 
  • #15
uart said:
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.
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.
 

What is class inheritance in C++?

Class inheritance in C++ is a feature that allows a new class (called the derived class) to inherit properties and behaviors from an existing class (called the base class). This allows for code reuse and helps to organize and structure code more efficiently.

How is class inheritance different from object composition?

In class inheritance, the derived class inherits the properties and behaviors of the base class, whereas in object composition, an object is created within another object to use its functionality. Inheritance represents an "is-a" relationship, while composition represents a "has-a" relationship.

What is the difference between public, private, and protected inheritance?

In public inheritance, the public and protected members of the base class are inherited as public and protected members in the derived class, respectively. In private inheritance, all members of the base class are inherited as private members in the derived class. In protected inheritance, the public and protected members of the base class are inherited as protected members in the derived class.

Can a derived class inherit from multiple base classes?

Yes, C++ supports multiple inheritance, where a derived class can inherit from more than one base class. This can be useful for creating complex class relationships and organizing code, but it can also lead to ambiguity and potential problems if not used carefully.

What is the purpose of virtual inheritance?

Virtual inheritance is used in cases where there are multiple paths from a derived class to a base class. It ensures that only one instance of the shared base class is created, preventing potential issues such as duplicate member variables. This is commonly used in the diamond problem, where a derived class inherits from two classes that both inherit from the same base class.

Similar threads

  • Programming and Computer Science
2
Replies
36
Views
2K
  • Programming and Computer Science
2
Replies
35
Views
2K
  • Programming and Computer Science
Replies
17
Views
1K
  • Programming and Computer Science
2
Replies
36
Views
2K
  • Programming and Computer Science
Replies
5
Views
1K
  • Programming and Computer Science
Replies
19
Views
924
  • Programming and Computer Science
2
Replies
36
Views
2K
  • Programming and Computer Science
Replies
9
Views
1K
  • Programming and Computer Science
Replies
31
Views
2K
  • Programming and Computer Science
Replies
6
Views
3K
Back
Top