So my Idea is simple - to have a class that can have its own public methosds and a nested class that would forvard only some of that public methods (pseudocode):
class API
{
public:
go();
stop();
friend class B
{
public:
void public_request()
{
request();
}
void public_go()
{
go()
}
};
private:
void request(){}
};
Is it possible to implement such nested class in C++ and how?
It is possible to create a Local class in C++. Local class is a class defined inside an function.
But such an class has several restrictions. Read about it here in detail.
You cannot create Nested classes in C++ like Java though. Nested class is a class within the scope of another class.
The name of a nested class is local to its enclosing class(It is not visible outside the scope of the enclosing class). Unless you use explicit pointers or references, declarations in a nested class can only use visible constructs, including type names, static members, and enumerators from the enclosing class
Two important points to note with Nested classes are:
Member functions of a nested class follow regular access rules and have no special access privileges to members of their enclosing classes.
Member functions of the enclosing class have no special access to members of a nested class.
So You will need to use composition or explicitly pass a pointer or reference of object of outer class to the nested class
Yes, but you have to provide an instance of the outer class when you create the inner one... the two types are [mostly] independant, so B is not associated with any specific instance of API.
More pseudo-code
struct API {
void go();
struct B {
B(API& api) : api(api) { }
void go() { api.go(); }
};
};
API a;
B b(a);
b.go();
Alternatively, you can pass an instance of API to B's function [B::go(API&)]
struct API {
void go();
struct B {
void go(API& api) { api.go(); }
};
};
API a1, a2;
B b;
b.go(a1);
b.go(a2);
Further, API does not contain an instance of B unless you explicitely add an instance.
struct API {
struct B { };
B b;
};
Also, note that B does not need to be granted friendship by API. As an inner class, B can already access APIs private/protected members. The converse is not true, however... API can not access Bs private/protected members unless B grants it permission.
Not directly, at least not in the same way as in Java. Your nested class has to contain a pointer or a reference to the "outer" class.
Related
so I am trying to construct a class with helper method, namely:
class Type{
int a, b, c;
friend auto helper(auto);
friend auto test_helper(auto);
/* couples test with implement */
public:
void method(){
helper(this);
}
};
But making helper a friend function couples the test with implementation if we want to test helper.
So I want to make helper a free function, namely:
auto helper(int&,int&,int&);
auto test_helper(int&,int&,int&);
class Type{
int a, b, c;
public:
void method(){
helper(a,b,c);
}
};
This, however, makes the code a lot more tedious when data members are many. So, I came up with an idea to construct an helper struct that has exact data member as Type but with all data member being public, so that we'll be able to simply pass in the handle of such HelperType, maybe something like:
struct HelperType{
int a, b, c;
};
auto helper(HelperType* a);
auto test_helper(HelperType* a);
void Type::method(){
helper(static_cast<HelperType*>(this));
}
Is there any elegant approaches to construct such HelperType struct? Such as a generic wrapper or perhaps with inheritance?
I have no simple solution to create HelperType from Type (only things coming to mind involve heavy metaprogramming or macro usage). However building Type from HelperType would be quite trivial, using private inheritance. From Derived class (cppreference.com):
When a class uses private member access specifier to derive from a base, all public and protected members of the base class are accessible as private members of the derived class.
// Could be renamed "TypePrivateMembers" or "TypeData"
struct HelperType{
int a, b, c;
};
auto helper(HelperType* a);
class Type : private HelperType {
public:
// a,b,c can be accessed in Type class scope.
void method(){
helper(this);
}
};
Live demo
However, still from cppreference (emphasis mine):
Private inheritance can also be used to implement the composition relationship (the base class subobject is an implementation detail of the derived class object). Using a member offers better encapsulation and is generally preferred unless the derived class requires access to protected members (including constructors) of the base, needs to override a virtual member of the base, needs the base to be constructed before and destructed after some other base subobject, needs to share a virtual base or needs to control the construction of a virtual base. [...]
This is the recurring composition over inheritance debate. This question has already been asked many times on StackOverflow, here are a few interesting link on the topic (in general & for this specific case):
Prefer composition over inheritance ? (language agnostic)
When to use C++ private inheritance over composition?
I have a header file with 2 classes. class A (which is a very big class) and class B that inherits class A. I don't want people to be allowed to create objects of class A or even be able to see its static members. They should only to work with class B. What is the best way of doing that.
(Generally speaking A is a "helper class")
To restrict the creation of the class, make the constructor of class A private and declare class B as a friend class. This way only B can instantiate A.
class B;
class A
{
private:
A();
friend class B;
};
The same applies to methods (static or not): make them all private and the friend statement will allow B to access A's members.
Edit: works with protected as well.
I don't want people to be allowed to create objects of class A
What you are looking for is called an "abstract base class". In C++, any class that has at least one abstract member is automatically an abstract class, there is no additional keyword like in other languages.
class A
{
public:
virtual void Test() = 0; // abstract, has no implementation
};
class B : public A
{
public:
virtual void Test() {} // not abstract, has an implementation
};
int main()
{
A a; // this will produce a compiler error.
B b; // this is fine
return 0;
}
or even be able to see its static members
Well, don't make them public. Either make them protected or private and grant friend access to your B class.
Hello I am wondering why C++ standard allows us in nested classes to access outer class's private fields, while it forbids to access inner class's private fields from the outer class. I understand, that this example:
class OuterClass{
public:
class InnerClass{
public:
void printOuterClass(OuterClass& outer) {cout << outer.m_dataToDisplay;};
};
private:
int m_dataToDisplay;
};
is fine, because thing, that Inner class sometimes can be complicated. But I think following scenario is also fine:
class Algorithm{
public:
class AlgorithmResults{
public:
void readAlgorithmResult();
private:
void writeAlgorithmResult();
};
void calculate(AlgorithmResults& results, Arguments...){
//calculate stuff
results.writeAlgorithmResult(results);
}
};
For me this structure makes perfect sense, although it is not allowed in C++. I also noticed, that for some time both were allowed in Java, but now second example is also forbidden.
What is the reason, that first example is allowed and another is denied?
Essentially, within a scope names declared earlier in that scope are valid and can be used directly (unless they're shadowed). Code outside a scope can't directly use names declared inside the scope. E.g. code after a curly braces block, can't directly use variables declared inside that block (an example of indirect use is when the outside code has access to a pointer to a static variable inside the curly braces block).
For the second example, just make Algorithm a friend of AlgorithmResults:
class AlgorithmResults
{
friend class Algorithm;
The nested classes could access outer class's private fields, because it's a member of the outer class, just same as the other members.
[class.access.nest]/1
A nested class is a member and as such has the same access rights as any other member.
On the other hand, the outer class doesn't have special access rights on the nested class, they're just normal relationship.
The members of an enclosing class have no special access to members of a nested class; the usual access rules ([class.access]) shall be obeyed. [ Example:
class E {
int x;
class B { };
class I {
B b; // OK: E::I can access E::B
int y;
void f(E* p, int i) {
p->x = i; // OK: E::I can access E::x
}
};
int g(I* p) {
return p->y; // error: I::y is private
}
};
— end example ]
Counter question: Why would you want to allow it?
If you need an outer class have access to an inner class' private internals, you can befriend:
class Foo {
public:
class Frob {
friend class Foo;
int privateDataMember;
};
Foo () {
Frob frob;
frob.privateDataMember = 3735928559;
}
};
C++ has no device to unfriend, so allowing default private access to an outer class would steal you a class design tool and yield reduced default encapsulation.
When creating an instance of a nested class, is an instance of the nesting class being made too?
If not then the child only have access to static public (and protected) functions of the parent?
For example:
class a {
public:
void baz();
class b {
public:
void foo();
};
};
int main(){
a::b bar; //is an instance of a being made too?
bar.foo();
}
Two points:
Adressing your question title, the answer is yes, a derived class always contains a subobject of its base class(es). I'd also prefer base class and derived class over parent class and child class, because of the "is-a" relationship. A derived class instance is a base class instance, but a child is not a parent.
Addressing your question body, you don't have parent/child or base/derived classes. The construct you have there is a class nested inside some other class. This is something completely different. Basically, this just creates a second class who's name is nested inside the other class' "namespace". Creating an instance of the nested class does not create an instance of the nesting class though.
The "parent/child" terminology is commonly used to describe inheritance relationships, which your code doesn't have. Bearing that in mind, b doesn't have any data members or base classes of type a, so the answer is no. No object of type a is created.
Note that by virtue of being an inner class, b has access to a's non-public members.
void a::b::foo() {
a obj;
obj.some_private_member(); // OK
}
Class b is a member of class a. It is a nested type declaration. Neither subobject of this nested type is declared in the class a. So you may not call non-static member function foo because an instance of class b is required.
On the other hand, the definition of the nested class b does not include a subobject of class a. Any class has only those members that are declared inside the class definition.
So in this statement
a::b bar; //is an instance of a being made too?
there is created an instance of class b that according to its definition has only one member - member function foo
The new parameters given in class b will be the same ones as "a" along with any additional parameters.
class a {
public:
void bar();
}
class b : public a
{
public:
void foo();
}
I have 3 function in my class B. These three function have to access member function of other class A.
I did this by creating object of class A in class B constructor and tried to access that object in functions of class B. But its showing error.
How can i assess the same object in these three functions. Where i have to create object of class A
B::B()
{
A a;
}
B:: function()
{
a.fun(); //fun belongs to class A
}
B:: function1()
{
a.fun1(); //fun1 belongs to class A
}
I am getting error, How can i implement the same where i can access object a in both function.
You should add A as a member of your B class, and not as a local variable of the B constructor.
Try this:
class B
{
public:
B();
void function1();
private:
// This is your member, and you can access it from all of B's methods.
A m_a;
};
You need to make a a member variable of class B like this:
class B
{
private:
A a;
// ...
}
That will make it available to all the member functions of B.
(Making it private isn't necessary - the decision to make it private, protected or public depends on whether you want to make it available only within B, within B and B's derived classes, or everywhere.)