25

Members of a class are by default private in c++.

Hence, I wonder whether there is any possible use of creating a class that has all its members (variables and functions) set by default to private.

In other words, does there exist any meaningful class definition without any of the keywords public, protected or private?

mr_T
  • 2,571
  • 3
  • 22
  • 39
  • 1
    are you referring also to C-tor and d-tor being private? if yes, i don't see any design pattern that would make use of such a class. That class interface is fully hidden so no one can ever create an object out of it – NirMH Sep 11 '14 at 10:29
  • 14
    @NirMH A `friend` class/function could do it. – AlexD Sep 11 '14 at 10:32
  • 2
    Why do you assume that there must be such a class? “private by default” does not imply that *all* members should be private, merely that privacy should be, well, the default. – Konrad Rudolph Sep 11 '14 at 10:39
  • I did not assume that it had to be. I wondered whether there could be... *curiosity* – mr_T Sep 11 '14 at 11:08
  • 2
    I guess it is was done just to encourage encapsulation. And at least to give some meaning (except alias) to `class` specifier comparing to `struct` :) – GreenScape Sep 11 '14 at 12:26
  • The question in the title and at the end of the body are not the same (even if you leave out the "by default"). Even if a class definition uses none of those keywords, it may still have public methods; for instance `class tag {};` has a public special member functions (e.g. default and copy constructors, destructor). – Marc van Leeuwen Sep 11 '14 at 17:30
  • 1
    I think the intent is like having default deny rules in iptables. Selectively expose what you need to, by default hide everything else. It's meant for security and stability. External things shouldn't be modifying internal state except through member functions ideally. – hookenz Sep 11 '14 at 21:07
  • A class that has no friends and only private members is completely useless. Several years ago I received a rather strange and inscrutable warning message from a compiler when I erroneously created such a class. The warning message has improved since then, but the net result hasn't. Under optimization such a class disappears because it is useless. – David Hammen Sep 12 '14 at 05:11

7 Answers7

25

There is a pattern, used for access protection, based on that kind of class: sometimes it's called passkey pattern (see also clean C++ granular friend equivalent? (Answer: Attorney-Client Idiom) and How to name this key-oriented access-protection pattern?).

Only a friend of the key class has access to protectedMethod():

// All members set by default to private
class PassKey { friend class Foo; PassKey() {} };

class Bar
{
public:
  void protectedMethod(PassKey);
};

class Foo
{
  void do_stuff(Bar& b)
  {
    b.protectedMethod(PassKey());  // works, Foo is friend of PassKey
  }
};

class Baz
{
  void do_stuff(Bar& b)
  {
    b.protectedMethod(PassKey()); // error, PassKey() is private
  }
};
Community
  • 1
  • 1
manlio
  • 18,345
  • 14
  • 76
  • 126
18

Tag dispatching. It's used in the standard library for iterator category tags, in order to select algorithms which may be more efficient with certain iterator categories. For example, std::distance may be implemented something like this: (in fact it is implemented almost exactly like this in gnu libstdc++, but I've modified it slightly to improve readability)

template<typename Iterator>
typename iterator_traits<Iterator>::difference_type
distance(Iterator first, Iterator last)
{
      return __distance(first, last,
             typename iterator_traits<Iterator>::iterator_category());
}

Where __distance is a function which is overloaded to behave more efficiently for std::random_access_iterator_tag (which is an empty struct, but could just as easily be a class), simply using last - first instead of the default behavior of counting how many increments it takes to get first to last.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • 2
    Doesn't really answer the question - tags have no members at all. The problem with all-private members is that you have untouchable state. – MSalters Sep 11 '14 at 12:19
  • 8
    @MSalters: *"does there exist any meaningful class definition without any of the keywords public, protected or private?"* -- A tag, or any other class with no members, fits that description. Perhaps the OP was assuming the examples would have one or more members (perhaps because it didn't occur to him that an empty class could be useful), but until he states that, I think this does answer the question. – Benjamin Lindley Sep 11 '14 at 12:25
  • I did not explicitly state it, and I found this example also very interesting indeed. – mr_T Sep 15 '14 at 06:38
16

Application wide resource acquisition ?

#include <iostream>

class C {
    C() {
        std::cout << "Acquire resource" << std::endl;
    }


    ~C() {
        std::cout << "Release resource" << std::endl;
    }

    static C c;
};


C C::c;

int main() {
    return 0;
}

As stated in comments below, I have I mind an industrial application that had to "lock" some hardware device while the program was running. But one might probably found other use for this as, after all, it is only some "degenerated" case or RAII.


As about using "private" methods outside the declaration block: I use a static member here. So, it is declared at a point where private members are accessible. You're not limited to constructor/destructor. You can even (ab)use a static methods and then invoke private instance methods using a fluent interface:

class C {
    C() { std::cout << "Ctor " << this << std::endl; }
    ~C() { std::cout << "Dtor" << this << std::endl; }

    static C* init(const char* mode) {
        static C theC;

        std::cout << "Init " << mode << std::endl;
        return &theC;
    }

    C* doThis() {
        std::cout << "doThis " << std::endl;

        return this;
    }

    C* doThat() {
        std::cout << "doThat " << std::endl;

        return this;
    }

    static C *c;
};


C *C::c = C::init("XYZ")
            ->doThis()
            ->doThat();

int main() {
    std::cout << "Running " << std::endl;
    return 0;
}

That code is still valid (as all C members are accessible at the point of declaration of C::c). And will produce something like that:

Ctor 0x601430
Init XYZ
doThis 
doThat 
Running 
Dtor0x601430
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • 4
    @T_at'Ghent I have in mind an industrial application where I had to "lock" some hardware device while the program was running. – Sylvain Leroux Sep 11 '14 at 14:03
  • @T_at'Ghent The purpose of this code seems to to demonstrate the life cycle of such an object. You need to use your imagination to fill in what resource is being used. – Iron Savior Sep 11 '14 at 17:35
  • 2
    I thought it was impossible to actually create an object with a private destructor because of 12.4;11 "A program is ill-formed if an object of class type ... is declared and the destructor for the class is not accessible at the point of the declaration", but this example shows it is possible (the only object of type `C` declaration is inside the class definition itself). To ensure that _all_ methods are private, one should also explicitly declare or remove the other special member functions. – Marc van Leeuwen Sep 11 '14 at 17:39
  • Thank you all for your comments. The first version probably deserved some explanations, but I was in a hurry. So I take time this morning to elaborate this a little. – Sylvain Leroux Sep 12 '14 at 08:41
  • @MarcvanLeeuwen I don't have the relevant part of the specs in mind, but, as far as I understand it, private members _are_ accessible at the point of _declaration_ of the static data member. So you can initialize a static object using a private constructor. Even using a private static factory. And you can even call private method on the object at its initialization site, using _fluent interface_. I've edited my answer to show that possibility. – Sylvain Leroux Sep 12 '14 at 08:44
7

Meaningful? Good practice? Probably not, but here goes:

class DataContainer {
    friend class DataUser;
    int someDataYouShouldNotWorryAbout;
};

class DataUser {
public:
    DataUser() {
        container.someDataYouShouldNotWorryAbout = 42;
    }
private:
    DataContainer container;
};
ikh
  • 10,119
  • 1
  • 31
  • 70
AlexanderBrevig
  • 1,967
  • 12
  • 17
1

No, there is no sense in creating a class without public member variable and/or functions, since there wouldn't be a way to access anything in the class. Even if not explicitly stated, the inheritance is private as well.

Sure, you could use friend as suggested, but it would create unneeded convolution.


On the other hand, if you use struct and not class to define a class, then you get everything public. That may make sense.

For example :

struct MyHwMap {
  unsigned int field1 : 16;
  unsigned int field2 : 8;
  unsigned int fieldA : 24;
};
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • "there is no sense in creating a class without public member variable and/or functions" - not exactly true, class with only `protected` members may be of use to be inherited from. – Wojtek Surowka Sep 12 '14 at 10:57
  • @WojtekSurowka Not sure what would you do with an interface, who's member functions are not accessible. The question prohibits use of `protected` as well. [This](http://stackoverflow.com/a/25789125/476681) may be ok, but I love unit testing my code, and that requires public access. – BЈовић Sep 12 '14 at 11:05
0

An admittedly ugly case from many, many years ago and not in C++ but the idea would still apply:

There was a bug in the runtime library. Actually fixing the offending code would cause other problems so I wrote a routine that found the offending piece of code and replaced it with a version that worked. The original incarnation had no interface at all beyond it's creation.

Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45
0

A derived class can be all-private, even its virtual methods redefining/implementing base-class methods.

To construct instances you can have friend classes or functions (e.g. factory), and/or register the class/instance in a registry.

An example of this might be classes representing "modules" in a library. E.g. wxWidgets has something like that (they are registered and do init/deinit).

Pablo H
  • 609
  • 4
  • 22