A confusion about c++ inheritance - c++

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.

Related

C++: Why Protected Constructor Cannot be Accessed in the Derived Class?

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.

Derived class cannot access the protected member of the base class

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.

Why can't a friend function access the private variables of an inherited class?

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.

Can objects of derived classes in C++ be accessible by parent class?

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();
}

Do private elements in the base class add to the size of the derived class?

// inheritence experiment
#include"stdafx.h"
#include<iostream>
using namespace std;
class base
{
private:
int i;
};
class derived: public base
{
private:
int j;
};
int main()
{
cout << endl << sizeof(derived) << endl << sizeof(base);
derived o1;
base o2;
cout << endl << sizeof(o1) << endl << sizeof(o2);
}
I'm getting this output:
8
4
8
4
why's that so? private data members of a base class aren't inherited into the derived class, so why I am getting 8 bytes for both, the size of derived and o1 ?
Private members are inherited. You just cannot access them from your derived class.
The private members are actually in the derived class, they're just not accessible within the derived class. The private keyword is to prevent programmers that derive from the base class from changing values the designer of the base class didn't want you to change because it might alter the functionality of the base class.
Have a look here for a deeper explanation
Fragile base class
class base {
public:
base(int v) : m_value(v) { }
int value() { return m_value; }
private:
int m_value;
};
class derived : private base {
derived(int v) : base(v) { }
int value2() { return value(); }
};
int main()
{
derived d(2);
return d.value2();
}
How do you expect this to work if the private base class doesn't store the value somewhere?
Your choice of words "inherited into the derived class" makes me think you are confused about how inheritance works. Members from the base class are not inherited into or copied into the derived class. The derived class contains an instance of the base type, as a sub-object within the complete derived object, so a derived class is (usually) at least as large as the sum of its base classes.
Consider this code:
struct A {
private:
int i;
};
struct B {
int j;
};
struct derived : A, B {
int k;
};
An A object is laid out in memory as an int, and so is a B.
A derived object could be laid out in memory as an A object, followed by a B object, followed by an int, which means it is a sequence of three ints. Whether the base class members are public or private doesn't affect that.
Of course they are inherited -after all, the behavior of the base-class will probably depend on them being there-, they are just not accessible!
Inherited methods of the base class can still use the private memebers. They have to be there.