How to make a class "private"

As a minimal example, consider a library that provides a `Car`, and the `Car` has an `Engine` in it:

car.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef CAR_H
#define CAR_H

class Engine {
public:
    void vroom();
};

class Car {
public:
    void start();
private:
    Engine eng;
};

#endif // CAR_H 


car.cpp
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "car.h"

void Engine::vroom() {
    puts("vroom");
}

void Car::start() {
    eng.vroom();
}


How can I make the class `Engine` "private"? That is, for any user of the library, the class `Engine` shoule not be visible. The user should only have access to `Car`.

Some say that to achieve this, It is needed to put the definition of `Engine` outside the public header. However in my case the class `Car` refers to `Engine`, making this not possible.

Thanks!
You can move the Engine into the private scope of Car:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef CAR_H
#define CAR_H

class Car {
public:
    void start();
private:
class Engine {
public:
    void vroom();
};

    Engine eng;
};

#endif // CAR_H  
This way only Car has access to Engine

For the implementation Engine requires Car as an additional scope:
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "car.h"

void Car::Engine::vroom() { // Note: Car::
    puts("vroom");
}

void Car::start() {
    eng.vroom();
}
@coder777 , Thanks! This indeed works.

However, I think if the nested class is a little bit more complicated, this method could hamper readability.

Also this seems to make reusing the nested private class in other classes difficult.

Is there any other way around this?

Thanks!
Last edited on
is a car having an engine viable?

class car
{
private:
engine e;
...

also didn't quite understand your header problem; can a forward declare resolve it?
finally, the header you give to the user of a compiled library does not have to be the same one you compiled it with, it can be stripped down.
Last edited on
However, I think if the nested class is a little bit more complicated, this method could hamper readability.
I don't see why it would be more complicated? You just add a scope level. In my book Car::Engine is perfectly readable.

Also this seems to make reusing the nested private class in other classes difficult.
Isn't that the whole point:
for any user of the library, the class `Engine` shoule not be visible.


You can actually make it protected for inheritance or make another class friend. If you want to use the class freely don't make it private.
Make Engine part of the implementation. Have Car store a unique_ptr<> to an Engine. That way the user doesn't know anything about the Engine class.

[ Edit: Added ~Car() based on Jens Hirschmann's comment below.]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <memory>

// car.h, which you distribute to your customers

class Engine; 			// forward declaration
class Car {
public:
    Car();
    void start();
    std::unique_ptr<Engine>eng;
    ~Car();
};

// engine.h, which is part of the implementation, but not distributed
// to customers
class Engine {
public:
    void vroom();
};


// car.cpp
// #include "car.h"
// #include "engine.h"

Car::Car() : eng(new Engine) {}

Car::~Car() {}   

void Car::start() {
    eng->vroom();
}

// engine.cpp
// #include "engine.h"
#include <iostream>

void Engine::vroom() { // Note: Car::
    std::cout << "vroom\n";
}


int main()
{
    Car myCar;
    myCar.start();
}

Last edited on
Thanks for all the helpful comments! Now I understand this much better.

For the post by @dhayden, for it to work I have to define a destructor in the impl cpp file as described in https://stackoverflow.com/questions/9954518/stdunique-ptr-with-an-incomplete-type-wont-compile
Last edited on
Thanks. I've edited my post.
Topic archived. No new replies allowed.