I have read this question,
I still have doubts in my concepts of inheritance.I have tried to solve a homework assignment but I think that I still don't get the access levels. I have following questions in my mind,
Is protected and public
access specifier same? (I don't find a
difference)
My assignment is attached below,please help me out if it is incorrect.
The difference is that protected members are only visible/accessible to child classes.
class A {
public:
int a; // anything can access this member.
private:
int b; // only A can access this member.
protected:
int c; // A and every other class that inherits this member can access it.
};
No, they're not the same.
public means that any other class can access the member.
private means it's only accessible by it's own class
protected means it's accessible by the own class, and all classes derivated from the class
Example:
class 1 {
public void do1() { }
private void do3() { }
protected void do2 { }
1()
{
public void do1() { } // ok
private void do2() { } // ok
protected void do3 { } // ok
}
}
class 2 {
2()
{
1.do1() { } // ok
1.do2() { } // ERROR
1.do3 { } // ERROR
}
}
class 3 inherits class 1 {
3()
{
do1() { } // ok
do2() { } // ERROR
do3 { } // ok = this class can access the the protected member of it's base class
}
}
You seem to have forgotten the simplest and the most important aspect: Accessibility of members from an unrelated class / in a freestanding (non-member) function. Public members can be accessed from outside the class and the class hierarchy, private and protected ones cannot.
If you mean public vs protected inheritance, well, the answer is there on your charts.
Protected members of a Base class can only be accessed by the Base class and class derived from base class.
**Private Members** can be only accesed by its own class and cannot be accesed by the derived class.
**Public members** can be accessed by any class including the derived class.
Please check this question
Related
Suppose we have this:
class Father
{
struct features
{
string hairColor = blonde;
int age = 1;
bool dumb = true;
} m_Features;
public:
Father();
~Father();
bool isDumb() { return m_Features.dumb; }
};
Then we have another class:
class FatherHandler : private Father
{
public:
// constructors here
void handle(Father *fa);
};
And now in the implementation:
void FatherHandler::handle(Father *fa)
{
if (fa->isDumb)
{
m_Features.dumb = true;
}
}
The g++ compiler does not allow the above code because m_Features is private; however I'm inheriting from Father privately; therefore it should be allowed. How can the above code be modified such that FatherHandler can modify Father without triggering this compile-time error? Note that I inherit privately to denote the 'uses' criteria, rather than inheriting publicly which uses the 'is-a' criteria.
Inheriting privately means the public and protected members of the base class(es) are made private in the inheriting class. The derived class still cannot access the private members unless it is specified as a friend.
To simplify my problem, I have something like this:
class Base {
private:
protected:
int a,b;
string c;
public:
[some functions here]
}
class Derived : public Base{
[some variables and functions]
friend void function();
}
void function(){
int d[a][b];
[stuff]
}
basically, my void function needs to access stuff that is in the protected class of the base class. I'd like to keep those variables defined in the protected section. Is there anyway for function, which HAS to be friended into the Derived class, to be able to access a and b?
You can define private methods in Derived: any method in Derived can access the protected members of Base.
Function is a friend of Derived, so it can invoke those private methods in Derived, which in turn access the protected members of Base.
Edit to reply to the comment below
The get_a() member method and the a member data are members of their classes. Instances of those members exist within instances of their classes. They don't exist except within an instance, so to access them you need to access them via an instance of the class.
For example, something like this:
class Derived : public Base{
[some variables and functions]
friend void function(Derived& derived);
};
void function(Derived& derived)
{
int a = derived.get_a();
int b = derived.get_b();
// I don't know but even the following might work
int c = derived.a; // able to access field of friend's base class.
}
void test()
{
Derived* derived = new Derived();
function(*derived);
delete derived;
}
Your functions need to access a and b through an Instance of the class Derived as follows
void function()
{
Derived objectDerived;
int d[objectDerived.a][objectDerived.b];
[stuff]
}
I have a program where I need to make a base class which is shared between a dll and some application code. Then I have two different derived classes, one in the dll one in the main application. Each of these have some static member functions which operate on the data in the nase class. (They need to be static as are used as function pointers elsewhere). In its simplest form my issue is shown below.
class Base {
protected:
int var ;
};
class Derived : public Base {
static bool Process( Base *pBase ) {
pBase->var = 2;
return true;
}
};
My compiler complains that I cannot access protected members of pBase even though Derived has protected access to Base. Is there any way around this or am I misunderstanding something?
I can make the Base variables public but this would be bad as in my real instance these are a lump of allocated memory and the semaphores to protect it for multithreading.
Help?
In general (regardless of whether the function is static or not), a
member function of the derived class can only access protected base
class members of objects of its type. It cannot access protected
members of the base if the static type is not that of the derived class
(or a class derived from it). So:
class Base {
protected:
int var;
} ;
class Derived : public Base {
static void f1( Derived* pDerived )
{
pDerived->var = 2; // legal, access through Derived...
}
static bool Process( Base *pBase )
{
pBase->var = 2 ; // illegal, access not through Derived...
}
} ;
Access specifier applies to the Derived class handle (reference/pointer/object) and not the methods of Derived class itself. Even if the method was not static, you would have ended up with the same error. Because you are not accessing var with the derived handle. Demo.
The correct way is to provide a setter method:
class Base {
protected:
int var ;
public:
void setVar(const int v) { var = v; } // <--- add this method
};
Note: There is one more way out, but I am not sure if it's elegant.
(static_cast<Derived*>(pBase))->var = 2;
This code:
class B {
protected:
void Foo(){}
}
class D : public B {
public:
void Baz() {
Foo();
}
void Bar() {
printf("%x\n", &B::Foo);
}
}
gives this error:
t.cpp: In member function 'void D::Bar()':
Line 3: error: 'void B::Foo()' is protected
Why can I call a protected method but not take its address?
Is there a way to mark something fully accessible from derived classes rather than only accessible from derived classes and in relation to said derived class?
BTW: This looks related but what I'm looking for a reference to where this is called out in the spec or the like (and hopefully that will lead to how to get things to work the way I was expecting).
You can take the address through D by writing &D::Foo, instead of &B::Foo.
See this compiles fine : http://www.ideone.com/22bM4
But this doesn't compile (your code) : http://www.ideone.com/OpxUy
Why can I call a protected method but not take its address?
You cannot take its address by writing &B::Foo because Foo is a protected member, you cannot access it from outside B, not even its address. But writing &D::Foo, you can, because Foo becomes a member of D through inheritance, and you can get its address, no matter whether its private, protected or public.
&B::Foo has same restriction as b.Foo() and pB->Foo() has, in the following code:
void Bar() {
B b;
b.Foo(); //error - cannot access protected member!
B *pB = this;
pB->Foo(); //error - cannot access protected member!
}
See error at ideone : http://www.ideone.com/P26JT
This is because an object of a derived class can only access protected members of a base class if it's the same object. Allowing you to take the pointer of a protected member function would make it impossible to maintain this restriction, as function pointers do not carry any of this information with them.
I believe protected doesn't work the way you think it does in C++. In C++ protected only allows access to parent members of its own instance NOT arbitrary instances of the parent class. As noted in other answers, taking the address of a parent function would violate this.
If you want access to arbitrary instances of a parent, you could have the parent class friend the child, or make the parent method public. There's no way to change the meaning of protected to do what you want it to do within a C++ program.
But what are you really trying to do here? Maybe we can solve that problem for you.
Why can I call a protected method but not take its address?
This question has an error. You cannot do a call either
B *self = this;
self->Foo(); // error either!
As another answer says if you access the non-static protected member by a D, then you can. Maybe you want to read this?
As a summary, read this issue report.
Your post doesn't answer "Why can I
call a protected method but not take
its address?"
class D : public B {
public:
void Baz() {
// this line
Foo();
// is shorthand for:
this->Foo();
}
void Bar() {
// this line isn't, it's taking the address of B::Foo
printf("%x\n", &B::Foo);
// not D:Foo, which would work
printf("%x\n", &D::Foo);
}
}
Is there a way to mark something fully accessible from derived classes rather than only accessible from derived classes and in relation to said derived class?
Yes, with the passkey idiom. :)
class derived_key
{
// Both private.
friend class derived;
derived_key() {}
};
class base
{
public:
void foo(derived_key) {}
};
class derived : public base
{
public:
void bar() { foo(derived_key()); }
};
Since only derived has access to the contructor of derived_key, only that class can call the foo method, even though it's public.
The obvious problem with that approach is the fact, that you need to friend every possible derived class, which is pretty error prone. Another possible (and imho better way in your case) is to friend the base class and expose a protected get_key method.
class base_key
{
friend class base;
base_key() {}
};
class base
{
public:
void foo(base_key) {}
protected:
base_key get_key() const { return base_key(); }
};
class derived1 : public base
{
public:
void bar() { foo(get_key()); }
};
class derived2 : public base
{
public:
void baz() { foo(get_key()); }
};
int main()
{
derived1 d1;
d1.bar(); // works
d1.foo(base_key()); // error: base_key ctor inaccessible
d1.foo(d1.get_key()); // error: get_key inaccessible
derived2 d2;
d2.baz(); // works again
}
See the full example on Ideone.
Standard reference: https://en.cppreference.com/w/cpp/language/access#Protected_member_access
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; // OK
}
};
The third party library's class contains a protected member. How can I access it if we cannot modify the code of the third party library?
A protected member can only be accessed by the class itself, subclasses, or friend classes and methods. The only way to access the protected member is to subclass the class, then use your subclass to expose the protected member.
Eg:
class parent {
/* Other members */
protected:
int foo();
}
class child : public parent {
public:
int foo();
}
You should make a special wrapper for that class. Just inherit library's class and gain the access to protected members. Due to inheritance, it is possible to use the wrapper class instead of the base class in your following code.
You can access protected members from a derived class.
class A
{
protected:
int i;
};
class B : public A
{
void func()
{
i; //valid
}
};