#include <iostream>
class A {
protected:
void foo()
{}
};
class B : public A {
public:
void bar()
{
std::cout << (&A::foo) << std::endl;
}
};
int main()
{
B b;
b.bar();
}
Here I am trying to get address of protected member function of base class. I am getting this error.
main.cpp: In member function ‘void B::bar()’:
main.cpp:5: error: ‘void A::foo()’ is protected
main.cpp:13: error: within this context
make: *** [all] Error 1
Changing foo to public works. Also printing &B::foo works. Can you please explain why we can't get address of protected member function of base class?
B is allowed to access protected members of A as long as the access is performed through an object of type B. In your example you're trying to access foo through A, and in that context it is irrelevant whether B derives from A or not.
From N3337, §11.4/1 [class.protected]
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2) As described
earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denote C or a
class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C. [Example:
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
void mem(B*,D1*);
};
// ...
void D2::mem(B* pb, D1* p1) {
// ...
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK
// ...
}
// ...
—end example]
Your example is very similar to the code in D2::mem, which shows that trying to form a pointer to a protected member through B instead of D2 is ill-formed.
I was curious and tried the following example:
#include <iostream>
using namespace std;
class A {
public:
void foo()
{
}
};
class B : public A {
public:
void bar()
{
printf("%p\n", (&A::foo));
printf("%p\n", (&B::foo));
}
};
int main()
{
B b;
b.bar();
}
Actually, I see that &A::foo == &B::foo, so for protected member of base class you can use derived class member to take address. I suppose in case of virtual functions this will not work
Seems I found the answer. If we could get pointer of member function we can call it for other objects of type A (not this) which is not allowed.
It is not allowed to call protected member function in derived classes for objects other than this. Getting pointer would violent that.
We can do something like this:
#include <iostream>
class A {
protected:
void foo()
{}
};
class B : public A {
public:
void bar()
{
void (A::*fptr)() = &A::foo;
A obj;
(obj.*fptr)();
// obj.foo(); //this is not compiled too.
}
};
int main()
{
B b;
b.bar();
}
Related
EDIT:
The original program has multiple files as shown in here
I'm trying to access protected data member in my class from a friend member function of a different class.
I keep getting an access error:
9:32: error: invalid use of incomplete type 'class b' 5:7: error:
forward declaration of 'class b' In member function 'void b::f(a*)':
12:13: error: 'int a::i' is protected 20:47: error: within this
context
This is my code:
// Example program
#include <iostream>
#include <string>
class b;
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
class b{
public:
void f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
};
int main()
{
a a1;
b b1;
b1.f(&a1);
}
The issue is only superficially related to friend. It's rather due to circular dependencies of class definitions and member functions; a needs to know the definition of b because it refers to b::f. But the definition of b::f needs the definition of a, as it refers to a::i. Luckily, definitions of a class and its member functions can be separated from each other.
You can take the following measures to tackle this step by step:
declare class a;
define class b { /* ... */ };, but without defining its member functions (as they need access to a's definition
define class a { /* ... */ };, possibly with inline member function definitions
and finally define b's member functions.
This is how it looks like:
// Step 1:
class a;
// Step 2:
class b{
public:
void f(a* pointer);
};
// Step 3:
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
// Step 4:
void b::f(a* pointer)
{
std::cout<<pointer->a::i<<std::endl;
}
At the point where you try to declare the method of b a friend via friend void b::f(a* pointer);, the class b is incomplete. You cannot refer to members yet. On the other hand, b only needs a forward declaration for a:
// Example program
#include <iostream>
#include <string>
class a;
class b{
public:
void f(a* pointer);
};
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
void b::f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
int main()
{
a a1;
b b1;
b1.f(&a1);
}
Try this. You are trying to reference b::f before class b is defined.
// Example program
#include <iostream>
#include <string>
class a;
class b{
public:
void f(a* pointer);
};
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
void b::f(a* pointer)
{std::cout<<pointer->a::i<<std::endl;}
int main()
{
a a1;
b b1;
b1.f(&a1);
}
In a derived class If I redefine/overload a function name from a Base class,
then those overloaded functions are not accessable/visible to derived class.
Why is this??
If we don't overload the oveloaded function from the base class in derived class
then all the overloaded versions of that function are available to derived class
objects, why is this??
what is the reason behind this. If you explain this in compiler and linker level
that will be more helpful to me. is it not possible to support this kind of scinario??
Edited
For examble:
class B
{
public:
int f() {}
int f(string s) {}
};
class D : public B
{
public:
int f(int) {}
};
int main()
{
D d;
d.f(1);
//d.f(string); //hidden for D
}
Now object 'd' can't access f() and f(string).
TTBOMK this doesn't have a real technical reason, it's just that Stroustrup, when creating the language, considered this to be the better default. (In this it's similar to the rule that rvalues do not implicitly bind to non-const references.)
You can easily work around it be explicitly bringing base class versions into the derived class' scope:
class base {
public:
void f(int);
void g(int);
};
class derived : public base {
public:
using base::f;
void f(float);
void g(float); // hides base::g
};
or by calling the explicitly:
derived d;
d.base::g(42); // explicitly call base class version
The functions are available, you just need to call them explicitly:
struct A {
void f(){}
};
struct B : public A {
void f() {}
};
int main() {
B b;
b.f(); // call derived function
b.A::f(); // call base function
}
In the example below, why is B::f() called even though it is private?
I know this fact that :
Access is checked at the call point using the type of the expression used to denote the object for which the member function is called.
#include <iostream>
class A {
public:
virtual void f() { std::cout << "virtual_function"; }
};
class B : public A {
private:
void f() { std::cout << "private_function"; }
};
void C(A &g) { g.f(); }
int main() {
B b;
C(b);
}
Because the standard says so:
[C++11: 11.5/1]: The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [ Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f() {
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public,
// D::f() is invoked
pd->f(); // error: D::f() is private
}
—end example ]
The example is the same as yours, lol.
private functions can override public virtual functions from a base class. Accessability is, in a fact, completely ignored when determining whether a function overrides another, so even in
// Redundant private for clarity:
class A { private: virtual void foo(); };
class B : A { public: void foo(); };
B::foo overrides A::foo.
During compile time C++ compiler verifies accessibility of functions and methods based on their type. In function C variable g is of type A (checked during compilation of the code), in which method f is declared as public.
Take a look at this link
include <stdio.h>
class Base
{
protected:
int foo;
int get_foo() { return foo; }
};
class Derived : public Base
{
public:
void bar()
{
int Base::* i = &Base::foo;
this->*i = 7;
printf("foo is %d\n", get_foo());
}
};
int main()
{
Derived d;
d.bar();
}
I don't understand why my derived type can't make a pointer to the protected member of the base class. It has privilege to access the member. It can call the similarly scoped function. Why can't it make a member pointer? I'm using gcc 4.1.2 and I get this error:
test.cc: In member function ‘void Derived::bar()’:
test.cc:6: error: ‘int Base::foo’ is protected
test.cc:15: error: within this context
By trial and error I found a solution that makes some sense. Even if it is a base class inherited member that you are pointing to, the pointer should still be a member pointer of the Derived class. So, the following code works:
include <stdio.h>
class Base
{
protected:
int foo;
int get_foo() { return foo; }
};
class Derived : public Base
{
public:
void bar()
{
int Derived::* i = &Derived::foo;
this->*i = 7;
printf("foo is %d\n", get_foo());
}
};
int main()
{
Derived d;
d.bar();
}
If Base's members are scoped as private then you get the expected lack of access error.
Below is a subtle example of accessing an instance's protected field x.
B is a subclass of A so any variable of type B is also of type A.
Why can B::foo() access b's x field, but not a's x field?
class A {
protected:
int x;
};
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int v = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Here is the error I get with g++
$ g++ -c A.cpp
A.cpp: In member function ‘void B::foo()’:
A.cpp:3: error: ‘int A::x’ is protected
A.cpp:14: error: within this context
Since B is publicly inherited from A, A's protected member(s) become B's protected member(s), so B can access its protected members as usual from its member function(s). That is, the objects of B can access the protected members of B from its member functions.
But A's protected members cannot be accessed outside the class, using object of type A.
Here is the relevant text from the Standard (2003)
11.5 Protected member access [class.protected]
When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.102) Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any
class derived from that class).
And the example follows from the Standard (2003) itself as:
[Example:
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
void mem(B*,D1*);
};
void fr(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // OK (access through a D2)
p2->B::i = 4; // OK (access through a D2, even though naming class is B)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
B::j = 5; // OK (because refers to static member)
D2::j =6; // OK (because refers to static member)
}
void D2::mem(B* pb, D1* p1)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
i = 3; // OK (access through this)
B::i = 4; // OK (access through this, qualification ignored)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK
j = 5; // OK (because j refers to static member)
B::j = 6; // OK (because B::j refers to static member)
}
void g(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // ill-formed
}
—end example]
Note in the above example fr() is a friend function of D2, mem() is a member function of D2, and g() is neither a friend, nor a member function.
Consider:
class A {
protected:
int x;
};
class C : public A
{
};
class B : public A {
protected:
unique_ptr<A> a;
public:
B() : a(new C) // a now points to an instance of "C"
{ }
void foo() {
int w = a->x; // B accessing a protected member of a C? Oops.
}
};
In Public Inheritance:
All Public members of the Base Class become Public Members of the derived class &
All Protected members of the Base Class become Protected Members of the Derived Class.
As per the above rule:
protected member x from A becomes protected member of class B.
class B can access its own protected members in its member function foo but it can only access members of A through which it was derived not all A classes.
In this case, class B contains a A pointer a, It cannot access the protected members of this contained class.
Why can the B::foo() access the members of the contained class B pointer b?
The rule is:
In C++ access control works on per-class basis, not on per-object basis.
So an instance of class B will always have access to all the members of another instance of class B.
An Code Sample, which demonstrates the rule:
#include<iostream>
class MyClass
{
public:
MyClass (const std::string& data) : mData(data)
{
}
const std::string& getData(const MyClass &instance) const
{
return instance.mData;
}
private:
std::string mData;
};
int main() {
MyClass a("Stack");
MyClass b("Overflow");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
Why can B::foo() access b's x field, but not a's x field?
A protected member can only be accessed by other members of the same class (or derived classes).
b->x points to a protected member of an instance of class B (through inheritance), so B::foo() can access it.
a->x points to a protected member of an instance of class A, so B::foo() cannot access it.
Class B is not identical to class A. That's why members of class B cannot access non-public members of class A.
On the other hand, class B derives publicly from class A, so class B now has a (protected) member x which any member of class B can access.
Lets start with basic concept,
class A {
protected:
int x;
};
class B : public A {
public:
void foo() {
int u = x; // OK : accessing inherited protected field
}
};
Since child is inheriting parent, child gets x. Hence you can access x directly in foo() method of child. This is the concept of protected variables. You can access protected variables of parent in child directly.
Note : Here I am saying you can access x directly but not through A's object! Whats the difference ? Since, x is protected, you cannot access A's protected objects outside A. Doesnt matter where it is - If its main or Child . That's why you are not able to access in the following way
class B : public A {
protected:
A *a;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Here comes an interesting concept. You can access a private variable of a class using its object with in the class!
class dummy {
private :
int x;
public:
void foo() {
dummy *d;
int y = d->x; // Even though x is private, still you can access x from object of d - But only with in this class. You cannot do the same outside the class.
}
};
//Same is for protected variables.Hence you are able to access the following example.
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int y = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Hope it explains :)
C++ is complete Object Oriented Programming, where as Java is pure Object oriented :)