Derived class can't access protected member during instantiation [duplicate] - c++

#include <iostream>
class Base
{
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); // This does not compile
somethingProtected(); // But this is fine
}
};
int main()
{
Derived d;
d.somethingDerived();
return 0;
}
I thought that maybe only the protected members of this can be used and protected members of other instances are forever unreachable.
But:
class Derived : public Base
{
public:
void somethingDerived(Derived& d)
{
d.somethingProtected(); // This compiles even though d is
// potentially a different instance
}
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
}
};
I feel kind of nauseated by this, since I have been programming in C++ for some time, but I could not find any explanation for this behaviour.
EDIT:
It doesn't matter if it is the same or a different instance:
int main()
{
Derived d1, d2; // Two different instances
d1.somethingDerived(d2); // This compiles fine
d1.somethingDerived(d1); // This compiles fine
return 0;
}
EDIT2:
It seems that when it comes to access rights, it doesn't matter at all what instance of a class is being used:
class Base
{
public:
void something(Base& b) // Another instance
{
++b.a; // But can enter private members
}
private:
int a;
};

Even though access control in C++ works on per-class basis (as opposed to per-instance basis), protected access specifier has some peculiarities.
The language specification wants to ensure that you are accessing a protected member of some base subobject that belongs to the derived class. You are not supposed to be able access protected members of some unrelated independent objects of base type. In particular, you cannot access protected members of freestanding objects of base type. You are only allowed to access protected members of base objects that are embedded into derived objects as base subobjects.
For this reason, you have to access protected members through pointer->member syntax, reference.member or object.member syntax, where the pointer/reference/object refers to the derived class.
This means that in your example, protected member somethingProtected() is not accessible through Base objects, Base * pointers or Base & references, but it is accessible through Derived objects, Derived * pointers and Derived & references. Your plain somethingProtected() access is allowed, since it is just a shorthand for this->somethingProtected() where this is of type Derived *.
b.somethingProtected() violates the above requirements.
Note that in accordance with the above rules in
void Derived::somethingDerived()
{
Base *b = this;
b->somethingProtected(); // ERROR
this->somethingProtected(); // OK
}
the first call will also fail while the second one will compile, even though both are trying to access the same entity.

I believe you have some confusion on how to access base class members.
It is only this way:
class Derived : public Base
void drivedMethod() {
Base::baseMethod();
}
in your example you are trying to access a protected member of another instance.
a Derived instance will have access to it's own protected members but not to another class instance protected members, this is by design.
In fact accessing the protected members of another class, from another instance members or from the main function are in fact both under public access...
http://www.cplusplus.com/doc/tutorial/inheritance/
(look for the access specifier table to see the different levels)
Both examples prove the same thing for example:
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
here your Derived class is getting b as a parameter, so it is getting another instance of base, then because b.somethingProtected is not public it will not complie..
this will complie:
void somethingDerived()
{
Base::somethingDerived();
your second example complies fine because you are accessing a public method on another d class
> void somethingDerived(Base& b)
> {
> b.somethingProtected(); // This does not
> }

The Derived class can only access the protected base member in Derived objects. It cannot access the member in objects that are not (necessarily) Derived objects. In the cases that fail, you are trying to access the member via a Base &, and since this might refer to an object that is not Derived, the access can't be made.

What you have done is illegal in C++. A protected member can not be accessed by an object of a class. Only member functions can access protected members. protected members behave just like private members except while inherited by a derived class. Consider the program given below to understand the difference between private, public and protected members.
class Base
{
private:
void somethingPrivate()
{
std::cout << "sasa" << std::endl;
}
public:
void somethingPublic()
{
std::cout << "haha" << std::endl;
}
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingPublic(); // Works fine.
somethingProtected(); // This is also fine because accessed by member function.
//b.somethingProtected(); // Error. Called using object b.
//somethingPrivate(); // Error. The function is not inherited by Derived.
}
};

Related

Unable to access protected data of the superclass from within the subclass when it's a different object passed as a pointer [duplicate]

This question already has answers here:
Accessing protected members in a derived class
(8 answers)
Closed 3 years ago.
I'm trying several programs about inheritance, and it turned out that the following caused an error but I don't really know the rationale.
#include <iostream>
using namespace std;
class Base {
protected:
int x = 0;
};
class Derived: public Base {
// OK: access protected member via this
void g() { cout<<x; }
// OK: access protected member of other Derived
void h(Derived& d) { cout<<d.x; }
// FAIL: access Base class's protected member, why?
void f(Base& b) { cout<<b.x; }
};
int main() {}
I expect that the Derived class could access the ​Base class's public or protected data members and member function.
However it didn't work as what I was thinking about, could anyone help me light up my concepts?
There is not more to it than you already discovered. Derived instances may acces their protected members and those of other derived instances but not those of base class instances. Why? Because thats how protected works by definition.
For more details I refer you to cppreference (emphasize mine):
A protected member of a class Base can only be accessed
1) by the members and friends of Base
2) by the members and friends (until
C++17) of any class derived from Base, but only when operating on an
object of a type that is derived from Base (including this)
void f(Base& b) {cout<<b.x;}
Here you are trying to access a protected member of a different class. It does not matter that you also share the same base class. (still looking for a source)
void g() {cout<<x;}
In this example you are acccessing your own private member. (protected members of base class are inherited and protected in derived class)
void h(Derived& d) {cout<<d.x;}
Here you are accessing the private member of the same class. But for more on this look at this post: Access private elements of object of same class
From this documentation
A protected member of a class Base can only be accessed
by the members and friends of Base
this is not your case
by the members and friends (until
C++17) of any class derived from Base, but only when operating on an
object of a type that is derived from Base (including this)
this is your case, but the argument b is not such a derived type
The reason for protected member access is to allow a base class to define an interface for use by derived classes. That's not the same as allowing every different derived type special access to every base class object.
The code in your question seems like the example in the cppreference website and there we can see a good explanation for that limitation in the code comments:
struct Base {
protected:
int i;
private:
void g(Base& b, struct Derived& d);
};
struct Derived : Base {
void f(Base& b, Derived& d) // member function of a derived class
{
++d.i; // okay: the type of d is Derived
++i; // okay: the type of the implied '*this' is Derived
// ++b.i; // error: can't access a protected member through Base
// (Otherwise it would be possible to change other derived classes,
// like a hypothetical Derived2, base implementation)
}
};
So, if you have a
class Derived2: public Base {
};
The Derived class shall not be allowed to access Derived2 protected attributes as it is not a child of Derived2. The purpose of protected is not to allow siblings but children class access to members.
Full details in the standard:
http://eel.is/c++draft/class.access#:access_control,protected
http://eel.is/c++draft/class.access#class.protected

Function overriding of protected member function in multi level Inheritance [duplicate]

#include <iostream>
class Base
{
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); // This does not compile
somethingProtected(); // But this is fine
}
};
int main()
{
Derived d;
d.somethingDerived();
return 0;
}
I thought that maybe only the protected members of this can be used and protected members of other instances are forever unreachable.
But:
class Derived : public Base
{
public:
void somethingDerived(Derived& d)
{
d.somethingProtected(); // This compiles even though d is
// potentially a different instance
}
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
}
};
I feel kind of nauseated by this, since I have been programming in C++ for some time, but I could not find any explanation for this behaviour.
EDIT:
It doesn't matter if it is the same or a different instance:
int main()
{
Derived d1, d2; // Two different instances
d1.somethingDerived(d2); // This compiles fine
d1.somethingDerived(d1); // This compiles fine
return 0;
}
EDIT2:
It seems that when it comes to access rights, it doesn't matter at all what instance of a class is being used:
class Base
{
public:
void something(Base& b) // Another instance
{
++b.a; // But can enter private members
}
private:
int a;
};
Even though access control in C++ works on per-class basis (as opposed to per-instance basis), protected access specifier has some peculiarities.
The language specification wants to ensure that you are accessing a protected member of some base subobject that belongs to the derived class. You are not supposed to be able access protected members of some unrelated independent objects of base type. In particular, you cannot access protected members of freestanding objects of base type. You are only allowed to access protected members of base objects that are embedded into derived objects as base subobjects.
For this reason, you have to access protected members through pointer->member syntax, reference.member or object.member syntax, where the pointer/reference/object refers to the derived class.
This means that in your example, protected member somethingProtected() is not accessible through Base objects, Base * pointers or Base & references, but it is accessible through Derived objects, Derived * pointers and Derived & references. Your plain somethingProtected() access is allowed, since it is just a shorthand for this->somethingProtected() where this is of type Derived *.
b.somethingProtected() violates the above requirements.
Note that in accordance with the above rules in
void Derived::somethingDerived()
{
Base *b = this;
b->somethingProtected(); // ERROR
this->somethingProtected(); // OK
}
the first call will also fail while the second one will compile, even though both are trying to access the same entity.
I believe you have some confusion on how to access base class members.
It is only this way:
class Derived : public Base
void drivedMethod() {
Base::baseMethod();
}
in your example you are trying to access a protected member of another instance.
a Derived instance will have access to it's own protected members but not to another class instance protected members, this is by design.
In fact accessing the protected members of another class, from another instance members or from the main function are in fact both under public access...
http://www.cplusplus.com/doc/tutorial/inheritance/
(look for the access specifier table to see the different levels)
Both examples prove the same thing for example:
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
here your Derived class is getting b as a parameter, so it is getting another instance of base, then because b.somethingProtected is not public it will not complie..
this will complie:
void somethingDerived()
{
Base::somethingDerived();
your second example complies fine because you are accessing a public method on another d class
> void somethingDerived(Base& b)
> {
> b.somethingProtected(); // This does not
> }
The Derived class can only access the protected base member in Derived objects. It cannot access the member in objects that are not (necessarily) Derived objects. In the cases that fail, you are trying to access the member via a Base &, and since this might refer to an object that is not Derived, the access can't be made.
What you have done is illegal in C++. A protected member can not be accessed by an object of a class. Only member functions can access protected members. protected members behave just like private members except while inherited by a derived class. Consider the program given below to understand the difference between private, public and protected members.
class Base
{
private:
void somethingPrivate()
{
std::cout << "sasa" << std::endl;
}
public:
void somethingPublic()
{
std::cout << "haha" << std::endl;
}
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingPublic(); // Works fine.
somethingProtected(); // This is also fine because accessed by member function.
//b.somethingProtected(); // Error. Called using object b.
//somethingPrivate(); // Error. The function is not inherited by Derived.
}
};

Is there a way that I can access the values in the base class using the derived class?

I'm using c++ and i have no idea on how can i access the variables in my base class using the derived class.
I need to get the values in the base class and do an operation in the derived class, since all the functions in the base class contains arguments, when I call the function,
ex:
Baseclass.getvalue();
i can't put any arguments since it is not defined.
I already did the constructor parts like
class derivedclass:baseclass
{
//insert functions here.
};
derivedclass::derivedclass()
:baseclass()
{
//insert initialization here
}
but i still can't access the values. help? do i need to use virtual? if yes, how?
*this is a user-defined program
simply access the (public or protected) values as if they were part of your derived class.
class baseclass {
protected:
int m_value;
public:
baseclass();
virtual int getvalue();
};
class derivedclass : public baseclass {
void dosomething(void) {
// whoa: `m_value` is part of `baseclass`, and we can simply access it here!
std::cout << "value: " << m_value << std::endl;
// we can also use `getvalue()`
std::cout << "getvalue(): " << getvalue() << std::endl;
}
};
In this case, the inheritance is private, so the base subobject and its members are only accessible within the derived class and its friends. By default, members and base classes are private if the class definition is introduced with the class keyword, and public with the struct keyword. If you want to access them from outside, then you'll need public inheritance:
class derivedclass : public baseclass {/*...*/};
or
struct derivedclass : baseclass {/*...*/};
If the derived class doesn't hide the member by declaring a member with the same name, you can access it as if it were a member of the derived class. (If the inheritance is protected or private, then it will be protected or private within the derived class, and so may not be accessible).
If it is hidden, and you specifically want the base-class version, then you'll need to qualify the member name:
Derived.baseclass::getvalue()
but if this is the case, then there's something funky going on and the class interfaces probably need rethinking.

Why private members get inherited?

So private members in the base class are also in the inherited class but not accessible in it, right?
Are they actually in the memory allocated to the the inherited object?
Are they actually in the memory allocated to the the inherited object?
Yes, they need to exist. The private members are part of the implementation detail of the base class. Without them, in general, the base class wouldn't be able to function (which is why they exist in the first place).
Making them private just allows the base class to create its implementation however it chooses, without exposing that to anybody, including the subclass.
Yes. Just for example, you can use a public function from the base class that manipulates private data, even in an instance of the derived class:
class Base {
int x;
public:
Base() : x(0) {}
void inc() { ++x; }
void show() { std::cout << x << "\n"; }
};
class Derived : public Base {
};
int main() {
Derived d;
d.show();
d.inc();
d.show();
}
With a properly functioning compiler, this must display:
0
1
...showing that the data in the Base object is present in the Derived object, even though it's not (directly) accessible.
Of course with almost anything in C++, there's the "as-if" rule -- if the compiler can determine that it can somehow produce the correct observable behavior for the program, even without including the private part(s) of the base class, then it's free to do so. The most obvious example of this would be if you included something (member function or data) in the base class that was simply never used in practice.
Yes they are,
When object of the derived class is being constructed all of its base classes are first being constructed as well.
Consider this example:
class Base
{
int x;
public:
Base(int px)
: x(px)
{
}
};
class Derived : public Base
{
int y;
public:
Derived(int px, int py)
: y(py), Base(px)
{
}
};
This example compiles and works and Base is initialized (constructor is called) before you reach the body of the Derived constructor.

How to access protected base class function, from derived class through base class ptr

I have abstract class A, from which I inherit a number of classes. In the derived classes I am trying to access protected function in A trough A pointer. But I get a compiler error.
class A
{
protected:
virtual void f()=0;
};
class D : public A
{
public:
D(A* aa) :mAPtr(aa){}
void g();
protected:
virtual void f();
private:
A* mAPtr; // ptr shows to some derived class instance
};
void D::f(){ }
void D::g()
{
mAPtr->f();
}
The compiler error says : cannot access protected member A::f declared in class A.
If I declare mAPtr to be D*, instead A* everything compiles. And I don't understand why is this.
Relying on private access works on unrelated instances of the same type.
Relying on protected access works on unrelated instances of the same type (and of more derived types).
However, relying on protected access does not work on unrelated instances of a base type.
[n3290: 11.5/1]: When a friend or a member function of a derived
class references a protected nonstatic member function or protected
nonstatic data member of a base class, an access check applies in
addition to those described earlier in clause 11. Except when forming
a pointer to member (5.3.1), the access must be through a pointer
to, reference to, or object of the derived class itself (or any class
derived from that class) (5.2.5). If the access is to form a pointer
to member, the nested-name-specifier shall name the derived class (or
any class derived from that class).
So D or something derived from D, but not A.
It's an oft-questioned cute oddity about C++ that nonetheless is designed to try to avoid pitfalls. After all, you don't know what type *mAPtr really has.
A class containing a protected section means that this class allows derived classes to manipulate their base class in any way they choose (as far as the protected interface allows).
Class D objects can manipulate their own A part. In doing say they probably want to maintain some invariants.
Suppose there is (or will be in the future!) another class E, also inherited from A. Class E objects also can manipulate their own A part, and they may be enforcing different invariants.
Now, if a class D object was allowed to manipulate the A part of any object, it can't ensure the invariants. A D object may do something to the A part of an E object that breaks that E object. That's why it is not allowed.
But if you really want to, perhaps a way to call A::f, without exposing it to everybody, would be via a friend function.
class A;
namespace detail
{
void call_f(A*);
}
class A
{
friend void detail::call_f(A*);
private:
virtual void f() = 0;
};
namespace detail
{
void call_f(A* a) { a->f(); }
}
class D: public A
{
public:
void g() { detail::call_f(mAPtr); }
private:
void f() {}
A* mAPtr;
};
This relies on users being disciplined enough to stay out of namespaces whose name clearly indicates that it contains implementation details.
You forgot using ; after class declaration:
class A
{
protected:
virtual void f()=0;
};
class D : public A
{
public:
void g();
protected:
void f();
private:
A* mAPtr; // ptr shows to some derived class instance
};
Besides, you don't need to store base class pointer.