Can't access protected member - c++

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.

Related

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.

I cant understand this access modifier

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.

Inheritance and calling member functions

I'm fairly new to object-oriented program, so maybe this is a basic question, but I'd appreciate any help you can offer.
If I have a class B, which is derived from class A, is there some way for objects of class B to access class B's member functions from within member functions of class A? So in the example below I might have a call to function2 from within function1 if the object initially calling function1 is of type B. Is this possible, and if so, how do I accomplish it? Thanks!
class A
{
public:
int a;
int b;
A(){}
A(int a, int b) { this->a = a; this->b = b; }
int function1();// { call function2 if class B }
};
class B : public A
{
public:
int c;
int d;
B(){}
B(int c, int d) { this->c = c; this->d = d; }
int function2();
};
A function inside A doesn't have any idea of the fact that a class B which extends A exists and which methods it has.
To be able to invoke a specific method implemented in B from A you need to declare it in A as virtual, possibly pure virtual (= 0).
class A {
protected:
virtual void function2() = 0;
public:
void function1() { this->function2(); }
}
class B : public A {
protected:
void function2() override { ... }
}
A virtual method is resolved at runtime, this means that when invoked, the more specific implementation for the object on which it is called is executed. A pure virtual method doesn't have any base implementation, this makes A abstract and forbids its instantiation.
EDIT: a final note, don't call virtual methods from base constructors or destructors. It is dangerous and a bad practice, not that this is your case but you never know.
Yes. You need to define function2() as a virtual function in class A. Then calling it from function1 will result in B's function2() being called if the object is actually a B. For example:
class A
{
public:
int a;
int b;
A(){}
A(int a, int b) { this->a = a; this->b = b; }
int function1() { return this->function2(); }
virtual int function2() { return 0; }
};
class B : public A
{
public:
int c;
int d;
B(){}
B(int c, int d) { this->c = c; this->d = d; }
int function2() override { return 999; }
};
If there is no sensible implementation of function2 for A, then it would never make sense to have an A object. You can express this by declaring function2 to be pure virtual; e.g.
virtual int function2() = 0;
virtual allows you to override function in parent class.
class A
{
public:
A(){}
A(int a, int b):a(a), b(b) {}
int function1() { return this->function2(); }
virtual int function2() { //what function2 in parent class should do }
private:
int a;
int b;
};
class B : public A
{
public:
B(){}
B(int c, int d):c(c), d(d) {}
int function2() { //what function2 in child class should do }
private:
int c;
int d;
};

Junk values - Inheritance in C++

I have a class as follows:
class base
{
protected:
int x;
int y;
int z;
public:
base(int x, int y, int z)
{
x = x;
y = y;
z = z;
}
virtual void show();
};
I derive a class from the above as:
class derived : protected base
{
public:
int a;
int b;
int c;
derived(int a, int b, int x, int y, int z) : base(x, y, z) //initialising the base class members as well
{
cout<<a<<b<<x<<y<<z; //works fine
a = a;
b = b;
}
void show()
{
cout<<a<<b<<x<<y<<z; //show junk values
}
//some data members and member functions
};
In main(), I use:
derived d(1, 2, 3, 4, 5);
d.show();
The data members appear to have legal values inside the constructor. However, when I use a similar function, i.e. with the same visibility mode, junk values seem to appear.
a = a;
b = b;
should be
this->a = a;
this->b = b;
or, even better, use an initializer list:
derived(int a, int b, int x, int y, int z) : a(a), b(b), base(x,y,z)
{
cout<<a<<b<<x<<y<<z; //works fine
}
what you're doing is self-assigning the parameter, so the members don't get set.
You never initialize your member variables. a=a; will assign to the local variable a (the parameter), not the member variable. It should be this->a=a;. The same for the other members.

Accessing a base class member in derived class

I have a simple class as below
class A {
protected:
int x;
};
class B : public A {
public:
int y;
void sety(int d) {
y = d;
}
int gety() {
return y;
}
};
int main() {
B obj;
obj.sety(10);
cout << obj.gety();
getch();
}
How can I set the value of the protected instance variable A::x from an instance of the derived class B without creating an instance of class A.
EDIT: Can we access the value of A::x using the object of B? Like obj.x?
B is an A, so creating an instance of B is creating an instance of A. That being said, I'm not sure what your actual question is, so here's some code that will hopefully clarify things:
class A
{
protected:
int x;
};
class B : public A
{
public:
int y;
int gety() const { return y; }
void sety(int d) { y = d; }
int getx() const { return x; }
void setx(int d) { x = d; }
};
int main()
{
B obj;
// compiles cleanly because B::sety/gety are public
obj.sety(10);
std::cout << obj.gety() << '\n';
// compiles cleanly because B::setx/getx are public, even though
// they touch A::x which is protected
obj.setx(42);
std::cout << obj.getx() << '\n';
// compiles cleanly because B::y is public
obj.y = 20;
std::cout << obj.y << '\n';
// compilation errors because A::x is protected
obj.x = 84;
std::cout << obj.x << '\n';
}
obj can access A::x just as an instance of A could, because obj is implicitly an instance of A.
A::x is protected, so not accessible from outside, neither as A().x or B().x. It is however accessible in methods of A and those directly inheriting it (because protected, not private), e.g. B. So, regardless of semantics B::sety() may access it (as plain x or as A::x in case of shadowing by a B::x or for pure verbosity).
Note that B does not have FULL access to A::x. It can only access that member through an instance of a B, not anything of type A or deriving from A.
There is a workaround you can put in:
class A
{
protected:
int x;
static int& getX( A& a )
{
return a.x;
}
static int getX( A const& a )
{
return a.x;
}
};
and now using getX, a class derived from A (like B) can get to the x member of ANY A-class.
You also know that friendship is not transitive or inherited. The same "workaround" can be made for these situations by providing access functions.
And in your case you can actually provide "public" access to the x through your B by having public functions that get to it. Of course in real programming it's protected for a reason and you don't want to give everything full access, but you can.
You can just refer to it simply as x in class B
For example:
class B : public A
{
public:
...
void setx(int d)
{
x=d;
}
};