Protected member is supposed to be accessible from derived class.
Then, why I got the compiling error in the code below?
class A {
protected:
A() {};
};
class B : public A {
public:
void g() {
A a; // <--- compiling error: "Protected function A::A() is not accessible ...". Why?
}
};
int main() {
B b;
b.g();
}
I noticed there is a related post, but the class there is a template class. Mine is just a "regular" class.
Why the derived class cannot access protected base class members?
protected members could be accessed from derived class, but only when through the derived class.
A protected member of a class is only accessible
...
to the members and friends (until C++17) of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:
So you can't create an indpendent object of base class even in member functions of derived class.
Put it in another way, the protected members of the current instance of derived class could be accessed, but protected members of independent base class can't. E.g.
class A {
protected:
int x;
public:
A() : x(0) {}
};
class B : public A {
public:
void g() {
this->x = 42; // fine. access protected member through derived class
A a;
a.x = 42; // error. access protected member through base class
}
};
Protected member is supposed to be accessible from derived class.
Yes, but only when accessed via the this pointer. Not when accessed on a complety separate object. Which you are trying to do, when B::g() tries to construct a new A object.
Related
Consider the following example
class base
{
protected :
int x = 5;
int(base::*g);
};
class derived :public base
{
void declare_value();
derived();
};
void derived:: declare_value()
{
g = &base::x;
}
derived::derived()
:base()
{}
As per knowledge only friends and derived classes of the base class can access the protected members of the base class but in the above example I get the following error "Error C2248 'base::x': cannot access protected member declared in class " but when I add the following line
friend class derived;
declaring it as friend , I can access the members of the base class , did I do some basic mistake in the declaring the derived class ?
The derived class could access the protected members of base class only through the context of the derived class. On the other word, the derived class can't access protected members through the base class.
When a pointer to a protected member is formed, it must use a derived
class in its declaration:
struct Base {
protected:
int i;
};
struct Derived : Base {
void f()
{
// int Base::* ptr = &Base::i; // error: must name using Derived
int Base::* ptr = &Derived::i; // okay
}
};
You can change
g = &base::x;
to
g = &derived::x;
My compiler actually said I needed to add a non-default constructor to base because the field is not initialized.
After I added
base() : g(&base::x) {}
it did compile without problems.
Isn't the friend function supposed to access everything that is in Base class and Derived class? class Derived: public Base -> everything that is in private in Base is now public inside the class derived.
class Base
{
private:
int x;
};
class Derived : public Base
{
int y;
public:
void SetY(int value);
void friend SetX(Derived &d);
};
void SetX(Derived &d)
{
d.x = 100; // Why is this a problem?
// Isn't Base supposed to be public now that is inherited?
}
int main()
{
Derived d;
SetX(d);
}
Your friend function void friend SetX(Derived &d); of Derived class is a friend function of that class only and it can only access private members of Derived class only but not allowed to access any private or protected member of a Base class. Also even from a Derieve class you can not access private members of a Base class but can access only the public and protected members. To reach/access the private members of a Base class you have to use public member function of base class.
There are two types of inheritance in C++
class B{};
class D:public B{};
All I mentioned above is applicable in the above case. Even though you inharite base B class as public to a Derieve class D all the private members inharites to Derieve D as private, protected members as protected and public as public.
But if you inharite as private like below all the members of Base class would be now private to the Derieve class.
class B{};
class D:private B{};
In this case a friend function can not even access any member of Base class B.
Isn't the friend function supposed to access everything that is in Base class and Derived class?
No. It is a friend of Derived, so it is supposed to access everything that the Derived class can access.
class Derived: public Base -> everything that is in private in Base is now public inside the class derived.
No. Everything that was private in Base before, is still private.
The use of public/protected/private for inheritance means something different than it does for member access control.
The rules state that an in the case of a public specifier - object of derived class can be treated as object of base class (not vice-versa). What does that mean?
Can all public elements (in any class) be accessible by anything/anywhere?
Does this refer to the fact that for the parent class attributes and methods defined as public are accessible by the derived class. But in the case that the attributes and methods from the derived class are public they aren't accessible by the parent/base class?
In a public base class
Base class members How inherited base class members appear in derived class
private: x ------------------------> x is inaccessible
protected: y ------------------------> protected: y
public: z ------------------------> public: z
but what about in reverse?
I suppose the correct question would be "Can members (not objects) of derived classes in C++ be accessible by parent class?"
Public and protected members (data members and functions) of the base class are accessible to the derived class.
Public members of a class are accessible from anywhere. Of course, they need to be accessed through an instance of that class.
But in the case that the attributes and methods from the derived class are public theyaren't accessible by the parent/base class?
They can be if you have an instance of the derived class. You can then access the public members of the derived class from the base class.
Edit:
Example where base class member accesses public member of derived class and vice versa.
class Base
{
public:
void funcBase();
};
class Derived : public Base
{
public:
void funcDerived();
};
void
Base::funcBase()
{
Derived d;
d.funcDerived();
}
void
Derived::funcDerived()
{
Base b;
b.funcBase();
}
int main()
{
Base b;
Derived d;
b.funcBase();
d.funcDerived();
}
It means if you have Bar that is a derived class of Foo.
class Foo
class Bar : public Foo
So you can say, as expected
Foo* myFoo = new Foo;
Bar* myBar = new Bar;
You can also make a Foo from a Bar since a Bar is a type of Foo
Foo* myOtherFoo = new Bar;
You cannot make a Bar from a Foo, that is what "object of derived class can be treated as object of base class (not vice-versa)" means.
Bar* myOtherBar = new Foo;
You asked:
Can objects of derived classes in C++ be accessible by parent class?
Yes. See below for a pattern that I have seen a few times.
You also asked:
Can all public elements (in any class) be accessible by anything/anywhere?
Yes, of course.
Example pattern of base class accessing derived class members
Entity.h:
class Attribute;
class Entity
{
public:
Entity(Attribute* att);
void save(FILE* fp);
void print();
private:
Attribute* att_;
};
Attribute.h:
#include "Entity.h"
class Attribute : public Entity
{
public:
void save(FILE* fp);
void print();
};
Entity.cc:
#include "Entity.h"
#include "Attribute.h" // Needed to access Attribute member functions
Entity::Entity(Attribute* att) : att_(att) {}
void Entity::save(FILE* fp)
{
// Save its own data.
//...
// Save the Attribute
att_->save(fp);
}
void Entity::print()
{
// Print its own data to stdout.
//...
// Print the Attribute
att_->print();
}
when using inheritance, I read from a tutorial that says
Conversely, if the most restricting access level is specified (private), all the base class members are inherited as private and thus cannot be accessed from the derived class.
So I test following code but the derived class can still access the member of base class.
Why?
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
Polygon():width(10),height(10){}
};
class Rectangle: private Polygon {
public:
int area ()
{ return height; }
};
int main () {
Rectangle rect;
cout << rect.area() << '\n';
return 0;
}
output is 10
The derived type can access public and protected members of the base class. This is independent of the type of inheritance. But the members are all private in the derived type if the inheritance is private.
class Foo
{
public:
int i;
};
class Bar : private Foo
{
public:
void hello() {
++i; // OK, I can see Foo's public and protected members
}
};
int main()
{
Bar b;
b.hello(); // accesses i internally. OK
b.i; // Error, i is private in Bar
}
Private inheritance means that all the base members become private to the derived class. The derived class itself can still access the members, but no further derived classes can.
According to the C++ Standard
If a class is declared to be a base class for another class using the
private access specifier, the public and protected members of the
base class are accessible as private members of the derived class117.
So in your example protected data members of the base class
protected:
int width, height;
are accessible as private members of the derived class and any member function of the derived class can access its private dara members.
Consider the following code:
class Base
{
void f() { }
};
class Derived: public Base
{
public:
};
What can you change in the derived class, such that you can perform the following:
Derived d;
d.f();
If the member is declared as public in the base class, adding a using declaration for Base::f in the derived class public section would've fix the problem. But if it is declared as private in the base class, this doesn't seem to work.
This is not possible. A using declaration can't name a private base class member. Not even if there are other overloaded functions with the same name that aren't private.
The only way could be to make the derived class a friend:
class Derived;
class Base
{
void f() { }
friend class Derived;
};
class Derived: public Base
{
public:
using Base::f;
};
Since you make the names public in the derived class anyway so derived classes of Derived will be able to access them, you could make them protected in the base-class too and omit the friend declaration.
You cannot access a private member from the derived class. What you can do is make it protected, and use a using declaration:
class Base
{
protected:
void f() { }
};
class Derived: public Base
{
public:
using Base::f;
};