3

I am currently busy with inheritance and I'm working with a base class called Vehicle and a subclass called Truck. The subclass is inheriting from the base class. I am managing with the inheritance of the public members of Vehicle but can't access the private member called top_speed in the function void describe() const.

I know that one can do this in code (provided below) to access from the base class but it seems like I'm missing something. In the comment section in the code my question is stated more clearly for you.

void Truck::describe() const : Vehicle()  

/*I know this is a way->    : Vehicle() 
to inherit from the Vehicle class but how
can I inherit the top_speed private member of Vehicle in the
void describe() const function of the Truck class?*/

{
    cout << "This is a Truck with top speed of" << top_speed << 
    "and load capacity of " << load_capacity << endl;
}

Where in my Vehicle class it is:

class Vehicle
{
private:
    double top_speed;

public:
    //other public members
    void describe() const;
};

and in the Truck class it is this:

class Truck: public Vehicle
{
private:
    double load_capacity;
public:
    //other public members
    void describe() const;  
};

To be even more clear I am getting this error:

error: 'double Vehicle::top_speed' is private

What can I do in the void Truck::describe() const function to fix it?

Niall
  • 30,036
  • 10
  • 99
  • 142
Joe_B
  • 219
  • 3
  • 10
  • 19
  • 5
    `void Truck::describe() const : Vehicle()` is not valid syntax. Anyway, the point of private is that the member is not exposed to derived classes. There's a completely separate access specifier for that. – chris Jul 29 '14 at 13:26
  • 1
    In Simple, You can't access the private member from one class to another class. – Sathish Jul 29 '14 at 13:27
  • 1
    You could also `friend class Truck;` within class `Vehicle` if you're wanted to make pasta. (ie. *don't*). – WhozCraig Jul 29 '14 at 13:29
  • 1
    I hope you know `Truck`'s `describe` does not override `Vehicle`'s. – chris Jul 29 '14 at 13:32

3 Answers3

5

The cleanest way is to have a public accessor function in the base class, returning a copy of the current value. The last thing you want to do is expose private data to subclasses(*).

double Vehicle::getTopSpeed( void ) const {
    return this->top_speed;
}

and then use it in the Truck class like this:

void Truck::describe( void ) const {
   cout << "This truck's top speed is " << this->getTopSpeed() << endl;
}

(Yeah, I know, "this->" is superfluous but it's used for illustrating that it's accessing members/methods of the class)

(*) Because, really, if you're going to expose data members of superclass(es), then why would you use private/protected/public at all?

emvee
  • 4,371
  • 23
  • 23
  • A public getter is nothing more than the false illusion of encapsulation. getters are only slightly better than public members. – Luchian Grigore Jul 29 '14 at 13:35
  • 2
    @LuchianGrigore, Surely it has more merit when it is not paired with a public setter. – chris Jul 29 '14 at 13:37
  • I agree, but at some point you do need to access information kept in the base class; the "public API" of all your vehicles. There's very little one can do with the information without access to it. Making it a public getter is at least a safe way of exposing the information to the outside world. – emvee Jul 29 '14 at 13:38
  • This works perfectly! Thank you so much. I just thought of using getters and setters. – Joe_B Jul 29 '14 at 13:42
  • @Joe_B, *I am not allowed to make changes to the Vehicle class given.* – chris Jul 29 '14 at 13:43
  • @haavee This is not bad to expose property to subclass with protected if it is not supposed to be public. You're just saying that protected is useless which is not true. – Gall Jul 29 '14 at 13:53
4

Simply declare top_speedas protected

class Vehicle
{
protected:
    double top_speed;

public:
    //other public members
    void describe() const;
};

If you can't modify the base class then you just can't access it.

Gall
  • 1,595
  • 1
  • 14
  • 22
  • Yeah, I tried that and it worked perfectly but I am not allowed to make changes to the Vehicle class given. – Joe_B Jul 29 '14 at 13:36
  • @Joe_B Ok, if there is no getter or other way exposed to get the property then you can't do anything. – Gall Jul 29 '14 at 13:39
  • @Joe_B I don't know what you're supposed to do with that but can you use base class describe function to do what you need ? If this is as simple as your code, like output. – Gall Jul 29 '14 at 13:42
2

Joe_B said

I am not allowed to make changes to the Vehicle class given

Then, there is still a very hugly way to access private members of a class you cannot modify (3rd party for instance).

If verhicle.h (let's say that's the class you have no way to modify) is:

class Vehicle
{
private:
    double top_speed;

public:
    Vehicle( double _top_speed ) : top_speed( _top_speed ) {}
};

and truck.h is:

#include "vehicle.h"
class Truck: public Vehicle
{
private:
    double load_capacity;

public:
    Truck( double _load_capacity, double _top_speed ) : 
        Vehicle( _top_speed ), 
        load_capacity( _load_capacity ) 
    {}

    void describe() const
    {
        std::cout << "This is a Truck with top speed of " 
                  << top_speed 
                  << " and load capacity of " 
                  << load_capacity 
                  << std::endl;
    }
};

Compiling this will give the error

Vehicle::top_speed is private

Then, let's do this:

In trunk.h, change #include "vehicle.h" into:

#define private friend class Truck; private
#include "vehicle.h"
#undef private

Without modifying vehicle.h, you made Truck class be a friend of Vehicle class, and it can now access Vehicle's private members!

Please, do not comment that it is a very bad idea to do this as it breaks all C++ rules....I know, you only want to do this if:

  • You really need to access a private member and have no alternative
  • There's really no way you cannot modify vehicle.h
  • You definitely know what you are doing, because if the guy who coded Vehicle made this attribute private, it was most likely because he did not want you to access it...

I used to do this when customizing behaviour of some MFC classes in the past...I definitely could not change the header files defining them....

jpo38
  • 20,821
  • 10
  • 70
  • 151
  • What a tricky way! Is this working properly with multiple private declaration or whatever include hierarchy which could include a 'clean vehicle' header before this? – Gall Jul 30 '14 at 07:21
  • If there's multiple `private:` declarations, GNU compiler only issues a warning (saying class is already a friend), a pragma can easily remove it. Having other clean vehicule includes should not cause any problem. Note that Truck also becomes friend of all classes included by vehicle.h (and using private: keyword). I like this trick too (was proud of it when I used it...), if you like it, please vote up ;-) – jpo38 Jul 30 '14 at 08:57