I cant understand this access modifier - c++

I am the beginner of C++. And I have a programming test today. But I cant understand this examples.
class A
{
public:
int w;
};
class B : public A
{
public:
int x;
};
class C : private A
{
public: int y;
};
class D : protected B
{
public: int z;
};
int main()
{
D d;
d.w = 10; // compile error
}
I thought (D d; d.w = 10) is correct, but it has compile error.
D derived by B (protected), and B derived by A (public).
So, I think D can access A class member, because
Class B : public A
{ public:int x}
==>
Class B
{ public: int w; int x;}
and Class D : protected B
{ public: int z}
==>
class D
{public: int z; protected: int w, int x;}
Why I am wrong?? Thank you!

D can see members of A and B, but because of protected inheritance, only D and classes derived from D know that D is a B and can access B and A members. main is not derived from D, so main is not aware of D's inheritance of B and thus cannot access the inherited A and B members.

Related

How to access variable "a" of "class A" from object of "class D"

I have a Class B, which is inheriting Class A.
I have a Class C, which is inheriting Class B and Class A;
There is a variable named "a" in class A which I have to access in class D, but not by using resolution operator on class B for example , d.B::a;
#include<bits/stdc++.h>
using namespace std;
class A{
public:
int a;
};
class B : public A{
public:
int b;
};
class D : public B, public A{
public:
int d;
};
int main() {
D d;
d.B::a = 1; // This is working correctly on this path class D -\> class B -\> class A
d.a = 2;
/*
But This line gives the following error
Non-static member 'a' found in multiple base-class subobjects of type 'A':
class D -> class B -> class A
class D -> class A
*/
return 0;
}
int main() {
D d;
d.D::a = 2; //This is not working correctly on this path class D -\> class A
d.A::a = 2; //This is not working correctly on this path class D -\> class A
//How do I use Scope Resolution to access variable "a" from second path ?!
return 0;
}
B already inherits from A, so D should only inherit from B:
class A{
public:
int a;
};
class B : public A{
public:
int b;
};
class D : public B{
public:
int d;
};
If you had another class C that also inherits from A, and you would want D to inherit from B and C, then you would have the diamond problem. Then, to avoid ambiguity, you should write:
class A{
public:
int a;
};
class B : virtual public A{
public:
int b;
};
class C : virtual public A{
public:
int b;
};
class D : public B, public C{
public:
int d;
};
Virtual inheritance is key words for your problem.
Try this one :
#include<bits/stdc++.h>
using namespace std;
class A{
public:
int a;
};
class B : virtual public A{
public:
int b;
};
class D : public B, virtual public A{
public:
int d;
};
int main() {
D d;
d.B::a = 1; // This is working correctly on this path class D -\> class B -\> class A
d.a = 2;
std::cout << d.a;
/*
But This line gives the following error
Non-static member 'a' found in multiple base-class subobjects of type 'A':
class D -> class B -> class A
class D -> class A
*/
return 0;
}

Is there any way to make this C++ program error free or I have to remove one of x declared in one the inherited class

#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"Constructing A \n";}
~A(){cout<<"Destructinf A \n";}
int x;
};
class B : virtual public A
{
public:
B(){cout<<"Constructing B \n";}
~B(){cout<<"Destructinf B \n";}
int x=20;
};
class C : virtual public A
{
public:
C(){cout<<"Constructing C \n";}
~C(){cout<<"Destructinf C \n";}
int x=50;
};
class D : public B,public C
{
public:
D(){cout<<"Constructing D \n";}
~D(){cout<<"Destructinf D \n";}
};
int main()
{
D obj;
obj.x; //x invoked
cout<<obj.x<<"\n";
return 0;
}
Output
error: request for member ‘x’ is ambiguous
Although I have used virtual class, still I am getting the above error.Do I have to remove One of the x declared in class B and Class C or is there any way to solve this error
The lookup set for the name x in the derived class D includes two names in its direct base classes { B::x, C::x }. So using the unqualified name x in these statements
obj.x; //x invoked
cout<<obj.x<<"\n";
is ambiguous.
You could use qualified names like for example
D obj;
cout<<obj.B::x<<"\n";
cout<<obj.C::x<<"\n";
If you will remove the data member x in one of the base classes of the class D then there will be no ambiguity and you may write (for example if to remove the data member x in the class B)
D obj;
cout<<obj.x<<"\n";
cout<<obj.C::x<<"\n";
If you want tp have one data member with the name x then remove it from the both classes B and C as for example
class B : virtual public A
{
public:
B() { x = 20; cout<<"Constructing B \n";}
~B(){cout<<"Destructinf B \n";}
};
class C : virtual public A
{
public:
C(){ x = 50; cout<<"Constructing C \n";}
~C(){cout<<"Destructinf C \n";}
}
Pay attention to that the destructor should be declared as virtual.

C++ Exclude classes inherited through base class in derived class

In C++, is it possible to exclude a class inherited in the base class, from a subclass?
For example, if you have three classes like so:
class A
{
public:
int x;
};
class B : public A
{
public:
int y;
};
class C : public B
{
public:
int z;
};
Is it possible for class B to contain the variables x and y, while class C only contains y and z?
I think the closest thing to what you want to achieve is private inheritance.
struct A
{
int x;
};
struct B : private A
{
int y;
};
struct C : B
{
int z;
};
int main()
{
C c;
c.x = 5; // error. you're not allowed to access members from A
c.y = 3; // ok
c.z = 4; // ok
}
So the data of A is still going to be there but you just can't access it from outside of B.
If you want the data to not exist in C at all then the answer is No. Inheritance is literally having the content of your parents in the beginning of your struct.
struct A
{
int x;
};
struct B : A
{
int y;
};
in memory an instance of B will look like this:
struct B
{
int x;
int y;
}
Yes, it's possible to meet your variable inheritance constraints. Use friend classes. With the friendship semantics exposed by the keyword friend inside a class declaration, you can make a derived class to have access to the private members of its parent class. The link contains a full tutorial of the friendship semantics.
Your code would look like:
class A
{
private:
int x;
friend class B;
};
class B : public A
{
public:
int y;
};
class C : public B
{
public:
int z;
};
With this, class B has access to the private x of class A, but only from inside the definition of class B. Your variable inheritance constraint is met, class B contains (and can use) x and y, while class C contains y and z.
Another way could be by private inheritance, like this:
class A
{
private:
int x;
};
class B : private A
{
public:
int y;
};
class C : public B
{
public:
int z;
};
But this is much more stricter than the friend approach. Choose which one suits your need.

Can't access protected member

I have some difficulties understanding the following code. I have 3 classes: A, B and C. A has a private x of type int. B inherits A and everything from it. C inherits from B but protected. This means that both X and Y become inaccessible in class C. Also, get_x() and get_y() become protected in class C. So C should be able to acces the get_x() and get_y() functions but not x and y?
#include<iostream>
using namespace std;
class A
{
int x;
public: A(int i):x(i){}
int get_x(){ return x; }
};
class B: public A
{
int y;
public: B(int i,int j):y(i),A(j){}
int get_y(){ return y; } };
class C: protected B
{
int z;
public: C(int i,int j,int k):z(i),B(j,k){}
int get_z(){ return z; }
};
int main()
{
C c(1,2,3);
cout<<c.get_x();
cout<<c.get_y();
cout<<c.get_z();
return 0;
}
It seems like you understood 'protected inheritance' right but misunderstood 'protected members and methods'.
protected methods are inaccessible from outside of class.
Meaning
C c(1,2,3);
cout << c.get_x(); // THIS DOES NOT WORK.
where you can access get_x() is within class C.
class C: protected B
{
int z;
public: C(int i,int j,int k):z(i),B(j,k){}
int get_z(){ return z; }
int get_x_from_c() { return this->get_x(); } // THIS IS ALLOWED.
};
Here Even Object of type C class can not use the functions of class A and B. If you want access of member functions then make public access of B to C.
do this ...
class c : public B{.. then it will be able to access functions but remember not the member variables.

conversion from derived * to base * exists but is inaccessible

Why does the follwing code produce this error even though c is a struct and has a public inheritance by default??
struct c
{
protected:
int i;
public:
c(int ii=0):i(ii){}
virtual c *fun();
};
c* c::fun(){
cout<<"in c";
return &c();
}
class d : c
{
public:
d(){}
d* fun()
{
i = 9;
cout<<"in d"<<'\t'<<i;
return &d();
}
};
int main()
{
c *cc;
d dd;
cc = &dd;
cc->fun();
}
You need:
class d : public c
class inheritance is private by default.
When you privately inherit from a class or a struct, you explicitly say, among other things, that direct conversion from a derived type to a base type isn't possible.