I am developing a C++ class library. The classes have "public" methods aimed at users, and "protected" ones supplying extra services reserved for internal use.
The classes do not derive from each other. In my current model, they need to be explicitly declared friends of each other. Is there a more compact/convenient way to achieve the same effect ?
Example:
class A
{
public:
static int ExposedA() { return 1; }
static int ExposedB();
static int ExposedC();
private:
static int Internal() { return 0; }
friend class B;
friend class C;
};
class B
{
public:
static int ExposedA() { return 2 + A::Internal(); }
static int ExposedB() { return 2; }
static int ExposedC();
private:
static int Internal() { return 0; }
friend class A;
friend class C;
};
class C
{
public:
static int ExposedA() { return 3 + A::Internal(); }
static int ExposedB() { return 3 + B::Internal(); }
static int ExposedC() { return 3; }
private:
static int Internal() { return 0; }
friend class A;
friend class B;
};
int A::ExposedB() { return 1 + B::Internal(); }
int A::ExposedC() { return 1 + C::Internal(); }
int B::ExposedC() { return 2 + C::Internal(); }
In practice, maintenance of the friends list is tedious, and forward references force to move the definitions out of the classes.
I reckon the short answer is "no".
In the comments (for anyone reading this in the future), you identified your problem as "a case of intentional strong coupling" as stated in an answer to this question (emphasis mine):
In general, friend classes are useful in designs where there is intentional strong coupling: you need to have a special relationship between two classes. More specifically, one class needs access to another classes's internals and you don't want to grant access to everyone by using the public access specifier.
The answer goes on to state:
The rule of thumb: If public is too weak and private is too strong, you need some form of selected access: either protected or friend (the package access specifier in Java serves the same kind of role).
In other words, if public doesn't work for you, and private doesn't work for you, you are left protected and friend. If you also can't use protected, then you are stuck with friend by the process of elimination. You can't change the language (unless you want to submit a paper to the committee, but that's a whole other topic entirely). You are left to juggle the these access specifiers around the best way you can.
To the question of which way is the best way to use these specifiers, I have no answer. It's nearly impossible for me to know what juggle combination will work best for your situation. So far, your solution seems to be the best. Nothing off the top of my head seems better, given your constraints.
it is internal to the class library. Users should have no access, libraries in the class should have mutual access.
If I'm understanding you correctly (and I may not be), I will say that you do have the (untested) option of having dual headers: one for you, and one for the end user. In your header, you can make the function public like this:
// YouB.h
class B
{
public:
static int ExposedA() { return 2 + A::Internal(); }
static int ExposedB() { return 2; }
static int ExposedC();
// This is a public function. Your compiler should have no problem with other classes using it
static int Internal() { return 0; }
};
Then, you have a different header for your users:
// UserB.h
// YouB.h
class B
{
public:
static int ExposedA() { return 2 + A::Internal(); }
static int ExposedB() { return 2; }
static int ExposedC();
private:
// This is a now a private or protected function.
// I haven't tested this, so I don't know if the other access thing will work,
// but since it's solely an internal function, commenting it out or removing
// it completely should work too
static int Internal() { return 0; }
};
Related
I want to design a class having a function which should be restricted to be called from another class only. Specifically, in the given code
class Club
{
int id;
string name;
vector<string> members;
int generateId()
{
static int i=1;
return i++;
}
public:
Club(string name) { this->name = name; this->id = generateId(); }
void registerMember(string memberName) { members.push_back(memberName); }
int getId() { return id; }
};
class Application
{
vector<Club> clubs;
public:
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
}
};
An user(public user) can create an object of the class Club and register using the function registerMember() since it's public. I want the user to register via an object of the class Application, using the addMemberToClub() function only. If the user goes by the former way mentioned, I can't keep track of the user. Is there a way to enforce the latter?
I don't want to use the access modifier protected since inheritance has no meaning here.
I don't want to use the friend keyword, since it's considered bad practice.
Here is a "lock-and-key" way to permit another class (and only that class) or even a single function in another class to access just one member function, unlike friend which exposes all private members at the same time:
#include <iostream>
class Key;
class Locked
{
static const char* const Greeting;
public:
static Key secretive();
static void attacker();
};
struct Admin
{
void doit();
};
class Key
{
~Key() = default;
//friend class Admin;
friend void Admin::doit();
friend Key Locked::secretive();
};
void Admin::doit()
{
Locked::secretive();
std::cout << Locked::Greeting; // compile error
}
constexpr const char* Locked::Greeting = "Hello!\n";
Key Locked::secretive()
{
std::cout << Greeting;
return Key();
}
void Locked::attacker()
{
std::cout << Locked::Greeting; // ok, it's just private
Locked::secretive(); // compile error, it's locked down tight
}
int main()
{
Admin a;
a.doit();
std::cout << Locked::Greeting; // compile error
Locked::secretive(); // compile error
}
It also works around the "which class is declared first?" problem that prevents two classes from mutually friending individual member functions of each other, because the restricted operation needs to follow only a forward declaration of the key type; the full definition of the other type can (and in this example does) appear above the key definition, allowing individual members to be named in the key type's friend directive.
Note that in this solution the "obvious" fact that other members of the same class can access the locked function is NOT true. The compiler prevents Locked::attacker() from calling Locked::secretive().
Note also that I've used static in this example to minimize the number of objects I had to create, but the approach works just fine for non-static member functions too.
A potentially MUCH easier way to restrict what part of the program can call your protected function is with a simple flag:
class Application
{
static bool addingMember = 0;
public:
static bool isRegistrationOk() { return addingMember; }
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
addingMember = true;
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
addingMember = false;
}
};
void Club::registerMember(string memberName)
{
assert(Application::isRegistrationOk());
members.push_back(memberName);
}
Much easier to grok, but it's a runtime check not compile-time, and requires additional work to be made thread-safe. But it accomplishes the goal with no usage of friend or inheritance.
friend is an appropriate mechanism to use in this case. Make registerMember private in Club, and Club can grant friendship to Application:
class Club
{
// ...
void registerMember(string memberName) { members.push_back(memberName); }
public:
// ...
friend class Application;
};
Now only Application can call registerMember, and Club as well, of course.
Here's a demo.
I'd like to be able to group similar functions in a class into a group so I don't need to append each name with what it's about.
I've seen this question which says that you can't have namespaces within classes. I've also seen this question which proposes using strongly typed enums. The problem here though, is that I'm not sure whether or not these enums can actually accomodate functions?
The problem contextualised:
class Semaphore
{
public:
void Set(bool State){Semaphore = State;}
bool Get(){return Semaphore;}
void Wait()
{
while (Semaphore)
{
//Wait until the node becomes available.
}
return;
}
private:
bool Semaphore = 0; //Don't operate on the same target simultaneously.
};
class Node : Semaphore
{
public:
unsigned long IP = 0; //IP should be stored in network order.
bool IsNeighbour = 0; //Single hop.
std::vector<int> OpenPorts;
//Rest of code...
};
Currently, NodeClass.Get() is how I can get the semaphore. However this introduces confusion as to what Get() actually gets. I'd like to have something akin to NodeClass.Semaphore::Get(). Otherwise I'd have to have the functions as SemaphoreSet(), SemaphoreGet(), and SemaphoreWait(), which isn't too well organised or nice looking.
I had thought of just having the Semaphore class on it's own, and instantiating it within the other classes, but if I could stick with the inheritance approach, that would be nicer.
So essentially, is it possible to access inherited methods like InheritedClass.Group::Function()?
If you really want to do this, you could force the user to call with the base class name by deleteing the member function in the subclass:
class Base {
public:
void Set(bool) { }
};
class Derived : public Base {
public:
void Set(bool) = delete;
};
int main() {
Derived d;
// d.Set(true); // compiler error
d.Base::Set(true);
}
However, if the semantics of calling Set on the subclass are significantly different than what you'd expect them to be when calling Set on the base class, you should probably use a data member and name a member function accordingly as you've described:
class Base {
public:
void Set(bool) { }
};
class Derived {
public:
void SetBase(bool b) {
b_.Set(b);
}
private:
Base b_;
};
int main() {
Derived d;
d.SetBase(true);
}
I'm trying to design a library, opening only several interfaces to caller, without mess up its own internal access control. What is the proper way to do it?
For example, here is the library:
namespace ControlledLib {
class ThinkTrack1 {
friend class DeepThought;
friend class ThinkTrack2;
private:
int ResultA() { return 6; }
int ResultB() { return 5; }
};
class ThinkTrack2 {
friend class DeepThought;
private:
int ResultC() { ThinkTrack1 tt1; return tt1.ResultB() + 2; }
};
class DeepThought {
friend int DeepThoughtAnswers();
private:
int Answers() {
ThinkTrack1 tt1;
ThinkTrack2 tt2;
return tt1.ResultA() * tt2.ResultC();
}
int CreateWorld() {
return 7;
}
};
int DeepThoughtAnswers() { DeepThought dt; return dt.Answers(); }
}
, it can be called by
#include "ControlledLib.h"
int i = ControlledLib::DeepThoughtAnswers();
The actual answer is given by class DeepThought's function Answers(), however, to make only one Answers() accessible to external callers, I have to make class DeepThought's functions private, and invent a global function DeepThoughtAnswers() as an entry point, which calls class DeepThought to get the answer, then class DeepThought has to define DeepThoughtAnswers() as a friend function.
It just begins. As class DeepThought actually calls class ThinkTrack1 and class ThinkTrack2, and class ThinkTrack2 calls class ThinkTrack1 and so on... To make all these unaccessible to external caller, all these functions are set to private, and I have to define a lot of friendship. Most of all, all these messed up the internal access control!
What would be a better way to do it?
When designing an interface there are some options you can choose from. The first is to just define a C interface that exports a set of functions. These functions internally call your classes, which are hidden through this layer.
<ControlledLib.h>
extern "C" int DeepThoughAnswers();
</ControlledLib.h>
In the source file the you have the implementation for this function:
<ControlledLib.cpp>
#include "DeepThought.h"
#include "ThinkTrack1.h"
#include "ThinkTrack2.h"
int DeepThoughAnswers()
{
DeepThought dt;
return dt.Answers();
}
</ControlledLib.cpp>
The files you include in this source then use visibility without friend and you only ship the resulting library and the ControlledLib.h file.
Another way is to use C++ interface to hide the implementation details. Here comes the interface:
<ControlledLib.h>
class ControlledLib
{
public:
virtual int DeepThoughAnswers() = 0;
};
</ControlledLib.h>
Then you have an implementation of this interface, which might look like this:
<MyControlledLib.h>
class MyControlledLib : public ControlledLib
{
public:
virtual int DeepThoughAnswers();
void someOtherFunction(); //<-- not visible to the 'outside'
};
</MyControlledLib.h>
Furthermore you add a factory that allows the client to instantiate your library.
<ControlledLib.h>
#include "ControlledLib.h"
class MyControlledLibFactory
{
public:
static MyControlledLib* create();
};
</MyControlledLib.h>
To the client you only ship the factory and the interface, everything else is hidden.
So far, your interface only uses primitive types, which means you do not have to export anyting else. In case you want to use classes in your interface you need to export those for the usage, too.
<ControlledLib.h>
class ControlledLib
{
public:
virtual int DeepThoughAnswers() = 0;
virtual ComplexAnswer* DeepThoughAnswersAreComplex() = 0; //<-- ComplexAnswer header needs to be supplied too.
};
</ControlledLib.h>
I would recommend you to use more of protected keyword and reduce use of friend keywords and redesign the interface again as its looking messy. A bridge design pattern for the implement and interface will be good and you can hide the implementations as a library and distribute the interface as header files only.
I dont have experience in programming so I want to ask about your opinion. For example I have 3 classes:
class A
{
public:
A(int size);
int getSize();
private:
int size_;
};
class B
{
public:
A* getChild(int childNumber);
int getNChildren()
{
return children.size();
}
private:
std::vector<A> children;
};
class C
{
public:
void sumSize()
{
int sum = 0;
for(int i = 0; i < member.getNChildren(); i++)
{
sum += member.getChild(i)->getSize(); // here I wonder if this is good style
}
}
private:
B member;
};
Is this a bad practice? I know I can have method sumSize() in class B and return this sum, but can I do it in this way or in bigger program there will be a complication?
So here is my main questions:
Should I avoid returning pointer to member: A* getChild(int
childNumber);
Everything which refer to children, should be compute
in class B?
I believe you are describing a container design pattern, which is well respected and useful. As the designer if you decide that member functions are public then you intend to let the "outside world" access them, and that decision depends upon what you are trying to accomplish.
Perhaps you don't want the outside world to modify this member, and so perhaps const A* getChild(int childNumber) might be what you want.
It is a good habit to think about "const-ness" as you design, all three of you public member functions in your example could be const (e.g int getSize() const) without affecting the functionality you have demonstrated.
One mistake here is the use of operator as a name of a private data member. operator is a reserved keyword in C++.
Suppose I have my classes as:
namespace scope
{
class A
{
private:
int a;
public:
...
};
class B
{
public:
...
A method();
...
};
};
The method definition:
A B::method()
{
A object;
object.a = 3; // private member access error
// access via object (pointer) error if inheritance is used
return object;
}
The most common way to solve the access error is to use setters+getters.
However I don't want any other scope (or someone using the API) to set A.a, so a public setter method is forbidden for this case.
a may be public but it should be read-only on API side. It should be read+write on the source side, because, for instance, I want to set it with B::method. How can I achieve this behaviour?
I tried inheritance, also friend relation. I also played with immutable and const property declarations. The problem with these is, when I declare A object with the default constructor, property is set to some value like -918316838410 (which might arise from the fact that I'm not using extern, I'm not sure) and cannot be set by method later on.
Any ideas will be appreciated. Thanks in advance.
You want B to have access to A that you don't want other people to have?
That is friendship.
Add friend class B, into the class A definition, and all will be happiness.
btw the common examples for this are when I am using multiple classes to generate a single interface. Eg: things like list<> and map<> usually need node classes, and those classes often want friend access on each other. This breach of encapsulation is fine, since they are really one big class from a logical perspective.
Be warned, most people should use friends rarely or never, its mostly for library writers, not for general programming.
Just like Richard said, you can use friendship. But keep in mind that when you need friendship, you should probably think again about your design. As Richard saids too, maybe putting a as a parameter of A constructor should do exactly what you want.
Here is a working example with friendship :
#include <iostream>
namespace scope
{
class A{
friend class B;
private:
int a;
public:
void print(){
std::cout << a << std::endl;
}
};
class B{
public:
A method(){
A a;
a.a=3;
return a;
}
};
int main(){
scope::B b;
scope::A a = b.method();
a.print(); //just to see it works...
}
Here is a way to do the same without friendship and keeping a private (Ok its ugly :-)
#include <iostream>
namespace scope
{
class B;
class A
{
private:
int a;
public:
void print(){
std::cout << a << std::endl;
}
// A way to only allow B instances to give a correct value
// of "a" member
void pleaseClassBSetMyPrivateMember(B& b);
};
class B
{
public:
A method(){
A a;
a.pleaseClassBSetMyPrivateMember(*this);
return a;
}
int computeValueForMemberOfClassA(A& a){
// you can access public members of a to
// calculate the proper value of a.a member
return 3;
}
};
void A::pleaseClassBSetMyPrivateMember(B& b)
{
// ask for class B object the correct value for member a
a = b.computeValueForMemberOfClassA(*this);
}
};