Reputation: 2621
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
?
Upvotes: 25
Views: 2914
Reputation: 659
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).
Upvotes: 0
Reputation: 18902
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
}
};
Upvotes: 24
Reputation: 52000
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
Upvotes: 16
Reputation: 9093
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.
Upvotes: 0
Reputation: 64223
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;
};
Upvotes: 1
Reputation: 103703
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
.
Upvotes: 18
Reputation: 1987
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;
};
Upvotes: 7