c++ access-specifier understanding - c++

I have encountered the following response in a thread :
Protected members can be accessed from derived classes. Private ones can't.
class Base {
private:
int MyPrivateInt;
protected:
int MyProtectedInt;
public:
int MyPublicInt;
};
class Derived : Base
{
public:
int foo1() { return MyPrivateInt;} // Won't compile!
int foo2() { return MyProtectedInt;} // OK
int foo3() { return MyPublicInt;} // OK
};
class Unrelated
{
private:
Base B;
public:
int foo1() { return B.MyPrivateInt;} // Won't compile!
int foo2() { return B.MyProtectedInt;} // Won't compile
int foo3() { return B.MyPublicInt;} // OK
};
...
1) my question is:
I have read : "A class derivation list names one or more base classes and has the form:
class derived-class: access-specifier base-class
Where access-specifier is one of public, protected, or private, and base-class is the name of a previously defined class. If the access-specifier is not used, then it is private by default. " and "Private Inheritance: When deriving from a private base class, public and protected members of the base class become private members of the derived class.
"
SO...in our example class Derived : Base is equivalent to class Derived : private Base because no access-specifier has been defined, yet the code works as the writer said, so what am i missing?- i thought that Base class for the class Derived access-specifier is private therefore public and protected members of Base should be private for class Derived and can't be accessed... thanks!

Its a similar kind of idea. Rather than applying to which members of the class you can access, it applies to which base classes you can access.
class A
{
public:
void f();
};
class B : public A
{
public:
void g()
{
f(); // OK
A *a = this; // OK
}
};
class B2 : public B
{
public:
void h()
{
f(); //OK
A *a = this; // OK
};
};
B b;
A& ba = b;
class C : protected A
{
public:
void g()
{
f(); // OK, can access protected base
A *a = this; // OK, can access protected base
}
};
class C2 : public C
{
public:
void h()
{
f(); // OK, can access protected base
A *a = this; // OK, can access protected base
};
};
C c;
c.f(); // Not OK, allthough A::f() is public, the inheritance is protected.
A& ca = c; // Not OK, inheritence is protected.
class D : private A
{
public:
void g()
{
f(); // OK because A is a base of D
A *a = this;
}
};
class D2 : public D
{
public:
void h()
{
f(); //Not OK, A is inherited with private in D
A *a = this; //Not OK
};
};
D d;
d.f(); // Not OK, allthough A::f() is public, the inheritance is private.
D& da = d; // Not OK, inheritence is private.

Related

c++ Getting access to member outside from inheritance chain

I have the following design:
- one class A that has a protected member of class M.
- one class B that inherits from A and has a pointer to an object of class C
- one class C that needs to have access to the member of the class A
class A {
public:
A() : _member(0) {}
~A() { delete _member }
protected:
M _member;
}
class B : public A {
public:
B(){}
~B(){}
protected:
C* c;
}
class C {
// C needs to have access to _member
}
What design should be more appropriate to solve this issue ?
In pure OO terms, allowing a class to directly access the internal fields of another class is bad practice.
That said, C++ is not a pure OO language, and does allow for this (among other important deviations from OO).
To allow access to a private member to another class, you must designate that class to be a friend. Friendship, however is not passed to derived classes, therefore you must upcast the class to the type you need.
This is your simplest solution:
class A {
public:
A() : _member(0) {}
~A() { delete _member }
protected:
friend class C;
M _member;
}
class B : public A {
public:
B(){ c = new C(this); } // this call will cast the B* to an A* (important)
~B(){ delete c;}
protected:
C* c;
}
class C {
public:
C(A* a) { _a->_member = new M(); } //Now C can directly access _member in A
}
In such a way, any object derived from A can be turned back into an A* and used to access _member.
However, as previously stated, any classes derived from C will not gain access to _member, as friendship is not inherited, so a more comprehensive solution is required:
class M {
public:
void Foo() { printf("Foo called\n"); }
};
class A {
M* m;
friend class C;
public:
A():m(0) { ; }
};
class B :public A {
int id;
public:
B() { id = 0; }
};
class C {
public:
C() { _a = 0; }
C(A* a) { _a = a; }
protected:
M* getM() { return _a->m; }
void setM(M* m_) { _a->m = m_; }
private:
A* _a;
};
class D : public C {
public:
D(B* b): C(b) {
}
void Foo() {
setM(new M());
getM()->Foo();
delete getM();
setM(nullptr);
}
};
int main()
{
B* b = new B();
D d(b);
d.Foo();
delete b;
getchar();
return 0;
}
In this way, no classes derived from A provide direct access to _member, and no classes derived from C have direct access, but the member variable can still be accessed via C's protected API. This also prevents other external objects accessing it.
Make C a friend of A:
class A {
friend class C;
/*and so on*/
Then C can see all member variables and functions in A, even if they are private.

C++ Class in class method inheritance

I have the following structure, and I would like to call foo from D. How is it possible? I got the error message, that I commented at the line below.
class A
{
protected:
class B
{
public:
B(x)
{
//...
}
protected:
virtual void foo()
{
//...
}
};
};
class C : public A
{
protected:
class D : public A::B
{
public:
D(x) : B(x)
{
//empty
}
};
void bar()
{
D var = D(x);
var.foo(); //cant access protected member in class A::B
}
};
foo() is protected member function of B, means that foo() is only allowed to be called from its subclass( child class).
bar() is member function of C, and C is inheritance from A. So ,C is not subclass of B.
If you put bar in D, that's OK.As code below:
class A
{
protected:
class B
{
public:
B(int x)
{
//...
}
protected:
virtual void foo()
{
//...
}
};
};
class C : public A
{
protected:
class D : public A::B
{
public:
D(int x) : B(x)
{
//empty
}
// Here is OK, while D is subclass of B
void bar()
{
int x;
D var = D(x);
var.foo(); //cant access protected member in class A::B
}
};
// void bar()
// {
// int x;
// D var = D(x);
// var.foo(); //cant access protected member in class A::B
// }
};
int main(){
return 0;
}
Try a friend class. You can make D a friend of B, and that should allow D to call foo().
Actually you are trying to access from the class C a protected method of the class D ==> You can't access protected methods from the external of a class.
One solution could be to declare C as a friend class of D so C can access protected methods:
// ...
class D : public A::B
{
public:
D(x) : B(x)
{
//empty
}
// Declare C as friend of D
friend class C;
};
// ...
Adding the friendship declaration your code will compile and will work as expected.
You might want foo() to be public in D even though it is protected in A::B
If so you can add the following line after the public: line in the definition of D
using A::B::foo;
Thanks for the answer. Making the foo function public is really a solution, but I really want foo only available from inherited class. The friend modifier is a thing, what many people hate, because it gives you access for things, thats you should not access.
But also you were right guys, I should access B::foo from D (from constructor is not an option is my case). I could create a function, which calls the original foo, so my solution is:
class A
{
protected:
class B
{
public:
B(x)
{
//...
}
protected:
virtual void foo()
{
//...
}
};
};
class C : public A
{
protected:
class D : public A::B
{
public:
D(x) : B(x)
{
//empty
}
Dfoo()
{
B::foo();
}
};
void bar()
{
D var = D(x);
var.Dfoo();
}
};
The solution was easy, but I did not know that a function (what is not static) can be called like this :)

C++: How to enforce derived class to set base member variables?

I have a base class with a member variable (preferably private) and I need to enforce derived classes to initialize it with a value based on their implementation; much like a pure virtual function.
To clarify, I want to declare a member in Base, have derived classes initialize it, and if they don't they get a compiler error. In the following code, I declared default constructor of Base to be protected. Then declared default constructor of Derived to be private.
class Base {
private:
int _size;
protected:
Base(){}
/* pure virtual methods */
public:
Base(int size) : _size(size){} // must enforce derived to call this.
virtual ~Base(){}
/* more pure virtual methods */
};
class Derived : public Base {
private:
Derived() {}
public:
Derived(int size) : Base(size) {
//Base::Base(size);
}
};
int main()
{
Derived* d1 = new Derived(); // throws an error as needed:
// "Cannot access private member declared in class 'Derived'"
Derived* d2 = new Derived; // throws an error as needed:
// "Cannot access private member declared in class 'Derived'"
Derived* d3 = new Derived(5); // works as needed
return 0;
}
The problem with the above code is that if another definition of Derived doesn't hide the default constructor. I'm still stuck with an uninitialized Base::_size.
I don't know if there is another way to go about this other than inheritance, because I still need derived classes to implement their own behavior for several methods declared in Base.
Any pointers are appreciated.
After the confusion about calling a base class ctor and default ctors, maybe the solution is just to not have a default ctor in Base?
class Base {
private:
int _size;
public:
// no default ctor
Base(int size) : _size(size) {} // must enforce derived to call this.
virtual ~Base(){}
/* more pure virtual methods */
};
class Derived : public Base {
public:
// no default ctor
Derived(int size) : Base(size){
}
// examplary default ctor:
//Derived() : Base(42) {}
};
int main()
{
Derived d1; // error: no default ctor
Derived* d2 = new Derived; // same, but why use the free store?
Derived d3(5); // works as needed
Derived* d4 = new Derived(5); // same, but why use the free store?
return 0;
}
To be explicit about not having a default ctor, one could use
class Base {
/* ... */
Base() = delete;
/* ... */
};
Use a constructor
class Base1 {
protected:
Base1(int forward) {
thingYouWantToHide = forward;
}
private:
int thingYouWantToHide;
};
class Derived1: public Base1 {
public:
Derived1(): Base1(5) {}
};
class Base2 {
private:
int value;
protected:
Base2() {
value = calledToGet();
}
virtual int calledToGet() = 0;
virtual ~Base2() {} //shut compiler warnings up
};
class Derived2: public Base2 {
virtual int calledToGet() {
return 5;
}
};
int main(int,char**) {
Derived1 a;
Derived2 b;
return 0;
}
You may think Derived2 will work, but remember Derived2 is not constructed until Base2 is, so that virtual is an undefined reference when Base2 is being constructed.
You should use the first case, type-traits if it is a constant (static const) or fundamental to the type.

Allow class access to single private member

I have a class A which has a private method called a(). I have also a class B which needs to access a() (but just B should have access to a(), thats why a() is private). I could now use a friend specifier but that would make other private methods of A (lets call them b() and c()) also available to B and I dont want that behaviour.
Is there a way to make just a() of A accessable to B?
There is a way -- if your class has a public template function:
class A {
// apparently private
void priv () { std::cout << "got you A::a()" << std::endl ; }
public:
template <class T>
void abuse() {}
};
struct Thief {};
template <>
void A::abuse<Thief>() {
this->priv();
}
int main() {
A a;
// obviously do not compile : a.priv();
// this i OK
a.abuse<Thief>();
return 0;
}
I must confess I stole this from GotW...
No there's not, but as you specify the precise class, just B could access A's private members.
You just have to take care of what method are called.
As friend relationship are not inherited, you don't have to worry about B's possible subclasses.
This could be done with some "twist".
Just factor out method a() from A class into a parent class that has B as a friend class, then let A inherit it. this will leave a() as being a method in A, but the only private method accessible by its parent's friend B.
here is a very simple code to clarify what I've said:
class parent
{
friend class B;
private:
void a() {}
};
class A:public parent
{
private:
void b() {}
void c() {}
};
class B
{
A* m_a;
public :
B()
{
m_a = new A();
m_a->a(); // OK
m_a->b(); // error C2248: 'A::b' : cannot access private member declared in class 'A'
}
};
hope it helps !
Yes, I have an easy way. Let B have a pointer of A::a(), like this:
typedef boost::function<void ()> functype;
class A {
private:
void a();
};
class B {
public:
void setfp(functype f) {m_f = f;}
void foo() {
// do some stuff
m_f();
}
private:
functype m_f;
};
A a;
B b;
b.setfp(boost::bind(&A::a, &a));
b.foo();

Accessing protected members in a derived class

I ran into an error yesterday and, while it's easy to get around, I wanted to make sure that I'm understanding C++ right.
I have a base class with a protected member:
class Base
{
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
This compiles and works just fine. Now I extend Base but still want to use b:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
Note that in this case DoSomething is still taking a reference to a Base, not Derived. I would expect that I can still have access to that.b inside of Derived, but I get a cannot access protected member error (MSVC 8.0 - haven't tried gcc yet).
Obviously, adding a public getter on b solved the problem, but I was wondering why I couldn't have access directly to b. I though that when you use public inheritance the protected variables are still visible to the derived class.
A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.
In your case, the Derived class can only access the b protected member of Derived instances, not that of Base instances.
Changing the constructor to take a Derived instance will solve the problem.
protected members can be accessed:
through this pointer
or to the same type protected members even if declared in base
or from friend classes, functions
To solve your case you can use one of last two options.
Accept Derived in Derived::DoSomething or declare Derived friend to Base:
class Derived;
class Base
{
friend class Derived;
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
You may also consider public getters in some cases.
As mentioned, it's just the way the language works.
Another solution is to exploit the inheritance and pass to the parent method:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
You have access to the protected members of Derived, but not those of Base (even if the only reason it's a protected member of Derived is because it's inherited from Base)
You can try with static_cast< const Derived*>(pBase)->Base::protected_member ...
class Base
{
protected:
int b;
public:
...
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b += static_cast<const Derived*>(&that)->Base::b;
d=0;
}
void DoSomething(const Base* that)
{
b += static_cast<const Derived*>(that)->Base::b;
d=0;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
Following the hack for stl I wrote a small code which seems to solve the problem of accessing the protected members in derived class
#include <iostream>
class B
{
protected:
int a;
public:
void dosmth()
{
a = 4;
}
void print() {std::cout<<"a="<<a<<std::endl;}
};
class D: private B
{
public:
void dosmth(B &b)
{
b.*&D::a = 5;
}
};
int main(int argc, const char * argv[]) {
B b;
D d;
b.dosmth();
b.print();
d.dosmth(b);
b.print();
return 0;
}
Prints
a=4
a=5
Use this pointer to access protected members
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
this->b+=that.b;
d=0;
}
};