How can classes in C++ be declared public, private, or protected?
In C++ there is no notion of an entire class having an access specifier the way that there is in Java or C#. If a piece of code has visibility of a class, it can reference the name of that class and manipulate it. That said, there are a few restrictions on this. Just because you can reference a class doesn't mean you can instantiate it, for example, since the constructor might be marked private. Similarly, if the class is a nested class declared in another class's private or protected section, then the class won't be accessible outside from that class and its friends.
By nesting one class inside another:
class A
{
public:
class B {};
protected:
class C {};
private:
class D {};
};
You can implement "private classes" by simply not publishing their interface to clients.
I know of no way to create "protected classes".
It depends if you mean members or inheritance. You can't have a 'private class', as such.
class Foo
{
public:
Foo() {} //public ctr
protected:
void Baz() //protected function
private:
void Bar() {} //private function
}
Or inheritance:
class Foo : public Bar
class Foo : protected Bar
class Foo : private Bar
Related
Consider the following
class Base;
class A {
int x;
friend class Base;
};
class Base {
protected:
A a_obj;
public:
Base(){
a_obj.x; // works
}
};
class Derived : public Base {
public:
Derived(){
a_obj.x; // not accessible
}
};
I could make public getters and setters for x, or make the object public, but that is not preferrable. Assuming there is a bunch of derived classes, adding friend class Derived in class A would make the code too verbose. Is there a way to say "A is friends with class Base and all it's children"
Is there a way to say "A is friends with class Base and all it's children"
No.
What you can do is make the base a friend (as you did), and write a protected accessor in the base that the children can use to access the private member.
In short, c++ rule is that friendship is not inheritable.
To achieve what you need, you can add static protected method as accessor in a Base class.
But, if you really need to make it w/o accessors or getters
you can make it with reinterpret_cast, but it would be hack and its not recommended.
Is there a way to say "A is friends with class Base and all it's children"
No
You need to fix your design. Classes should not be granted access to members of all types derived from a base class. As per your code, I think you need to modify the private member of a class in the constructor of other class.
One possible solution is using parameterized constructor. You can call constructor of class A from classes Base and Derived.
class Base;
class A {
int x;
public:
A(int in): x(in)
{
}
};
class Base {
protected:
A a_obj;
public:
Base(int in): A(in)
{
}
};
class Derived : public Base {
public:
Derived(): Base(5)
{
}
};
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.
I'm attempting a simple example of inheritance in C++. But I just can't get it down. When I try to get the protected members of class B inherited from class A it says that A::baz is protected.
#include <iostream>
class A {
public:
int foo;
int bar;
protected:
int baz;
int buzz;
private:
int privfoo;
int privbar;
};
class B : protected A {}; // protected members go to class B, right?
int main() {
B b;
b.baz; // here is the error [A::baz is protected]
}
I can't seem to find what I'm doing wrong. I've tried changing class B : protected A to : public A but it still doesn't work.
Protected inheritance just impacts how clients of your class see the public interface of the base class. Protected inheritance marks the public members of the base class as protected for users of your inherited class.
So baz in your example is not public, it is protected from B, hence the compiler error.
You can access protected members from inside a deriving class, not outside.
class B : protected A
{
void foo()
{
int x = foo; //ok
x = baz; //ok
x = privfoo; //error
}
};
Inheritance type only limits base class access. If, for example, you choose protected inheritance, all public methods in A will become protected to the outside, and the rest remain the same.
protected fields can only be accessed by methods in the class declaring them, or classes inheriting from the declaring class. you are trying to access a protected field ffrom a global function.
Because A::baz is protected, B can access it:
class B : public A
{
public:
int some_other_method()
{
return baz;
}
};
but that doesn't let other code access it.
The protected access specifier is similar to private. Its only
difference occurs in fact with inheritance. When a class inherits from
another one, the members of the derived class can access the protected
members inherited from the base class, but not its private members.
More on it here
You should read about public/private inheritance in C++. What you want to achieve is done by replacing
class B : protected A {};
by
class B : public A {};
EDIT: I read too fast and didn't notice you tried to access baz from main. You can only access it from a member method.
When a member is protected, it can only be accessed from within methods of the class that defines it and its descendants.
What you are trying to do is access the protected/private members from code external to these classes, which is not allowed. You can only access public members of a class from outside of class's scope.
If I have two classes for example as follows:
class A {...}
class B {...}
If I want to make class A public to class B, do I just make the members of class A public or I can just use public class A {...}?
Is there a way to tell class B for example that only class A is public for you? In other words, can I make public classes to A protected or private to others? Or, this is just a matter of deriving a class (inheritance)?
Thanks.
There's a substantial difference between making the class public and making its contents public.
If you define your class in an include file (.h file) then you are making your class public. Every other source file that includes this include file will know about this class, and can e.g. have a pointer to it.
The only way to make a class private, it to put its definition in a source (.cpp) file.
Even when you make a class public, you don't necessarily have to make the contents of your class public. The following example is an extreme one:
class MyClass
{
private:
MyClass();
~MyClass();
void setValue(int i);
int getValue() const;
};
If this definition is put in an include file, every other source can refer to (have a pointer to) this class, but since all the methods in the class are private, no other source may construct it, destruct it, set its value or get its value.
You make the contents of a class public by putting methods from it in the 'public' part of the class definition, like this:
class MyClass
{
public:
MyClass();
~MyClass();
int getValue() const;
private:
void setValue(int i);
};
Now everybody may construct and destruct instances of this class, and may even get the value. Setting the value however, is not public, so nobody is able to set the value (except the class itself).
If you want to make the class public to only some other class of your application, but not to the complete application, you should declare that other class a friend, e.g.:
class SomeOtherClass;
class MyClass
{
friend SomeOtherClass;
public:
MyClass();
~MyClass();
int getValue() const;
private:
void setValue(int i);
};
Now, SomeOtherClass may access all the private methods from MyClass, so it may call setValue to set the value of MyClass. All the other classes are still limited to the public methods.
Unfortunately, there is no way in C++ to make only a part of your class public to a limited set of other classes. So, if you make another class a friend, it is able to access all private methods. Therefore, limit the number of friends.
You can use friendship.
class A { friend class B; private: int x; };
class B { B() { A a; a.x = 0; // legal };
If B has a strong interdependence to A, i suggest you use a nested class. Fortunately, nested class can be protected or private.
class A {
protected:
// the class A::B is visible from A and its
// inherited classes, but not to others, just
// like a protected member.
class B {
public:
int yay_another_public_member();
};
public:
int yay_a_public_member();
};
I have three classes:
A data holder class CDataHolder, which uses a Pimpl pattern
class CDataHolder
{
public:
// ...
private:
friend class CBase;
struct PImpl;
PImpl* iPimpl;
};
A base class CBase, which need to access the iPImpl member in CDataHolder, so it is a friend class of CDataHolder
class CBase:
{
protected:
CDataHolder::Pimpl* getDataHolderPimpl();
};
A derived class CDerived from CBase, which need to access the same iPimpl member also. Here occurs a problem.
The derived class cannot use the iPimpl member although its parent class is a friend class. like this:
class CDerived : public CBase
{
public:
void doSth() {
CDataHolder::Pimpl *pImpl = getDataHolderPimpl(); // this line raises an error:
// "illegal access from CDataHolder to protected/private member CDataHolder::PImpl"
}
};
There are plenty of derived classes, so it's not a good way for each derived class to put a "friend class CDerivedXXX" line in CDataHolder class.
How to overcome this issue? Is there a better way to do this? Thanks in advance.
Since you have declared struct PImpl in the private part of CDataHolder class, only friends of CDataHolder can access the same. Why don't you put a forward declaration struct PImpl in the public section or even better before the CDataHolder class?
Friend is (rightfully) very limited and can't be inherited. I hate to beg the question, but maybe either A) you need public access to PImpl or some aspect of it, or B) you need the DataHolder class to do something with PImpl for you.