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.
Related
The base class pointer does not call the derived class method, while the Base class pointer points to the Derived class object.
using namespace std;
class Base
{
public:
virtual int f1() {cout<<"Base f1"<<endl;return 0;}
};
class Derived : public Base
{
public:
int f1() {cout<<"Derived f1"<<endl;return 0;}
int f2() {cout<<"Derived f2"<<endl;return 0;}
};
int main() {
Base* bp2=new Derived();
bp2->f2();
return 0;
}
The above program gives the error as:
main.cpp:28:10: error: ‘class Base’ has no member named ‘f2’; did you mean ‘f1’?
28 | bp2->f2();
| ^~
| f1
So when I can use the Base class pointer to call the derived class method.
Result is exactly as expected. The base class has no method f2, and that’s what the compiler tells you.
#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();
}
This question already has answers here:
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 8 years ago.
Consider the following code:
class Base
{
public:
void Fun()
{
}
};
class Derived : public Base
{
public:
void Fun(int x)
{
}
};
int main()
{
Derived d;
d.Fun(5);
d.Fun(); // Compilation error
}
On compilation, the compiler complains that there is no version of Fun() that takes zero arguments. Why is this so? I can understand compiler hiding the base class version if the function signatures match in Base and derived classes, but why is the compiler not able to resolve both functions if they take different parameters/different no. of parameters?
you have to create function body in derived class
void Fun()
{
}
Compile time first it will check function body in derived class.
You can use base class function if you are not overloading the function in derived class..
In the below example I changed the function name of derived class...
class Base
{
public:
void Fun()
{
}
};
class Derived : public Base
{
public:
void Fun1(int x)
{
}
};
int main()
{
Derived d;
d.Fun1(5);
d.Fun(); // No Compilation error
}
If you want to overload the function in derived class then you will have to override the base class function. like this
class Base
{
public:
void Fun()
{
printf("Base Class\n");
}
};
class Derived : public Base
{
public:
void Fun()
{
Base::Fun();
}
void Fun(int x)
{
printf("Derived Class\n");
}
};
int main()
{
Derived d;
d.Fun(5);
d.Fun(); // No Compilation error
}
compilation error, as there is no any 'Fun()' in derived class. You are calling Fun() by using derived class object. In CPP this is called as 'method hiding'. To solve this create function Fun() in derived class
void Fun()
{
}
How can I call a base class method which is overridden by the derived class, from a derived class object?
class Base{
public:
void foo(){cout<<"base";}
};
class Derived:public Base{
public:
void foo(){cout<<"derived";}
}
int main(){
Derived bar;
//call Base::foo() from bar here?
return 0;
}
You can always(*) refer to a base class's function by using a qualified-id:
#include <iostream>
class Base{
public:
void foo(){std::cout<<"base";}
};
class Derived : public Base
{
public:
void foo(){std::cout<<"derived";}
};
int main()
{
Derived bar;
//call Base::foo() from bar here?
bar.Base::foo(); // using a qualified-id
return 0;
}
[Also fixed some typos of the OP.]
(*) Access restrictions still apply, and base classes can be ambiguous.
If Base::foo is not virtual, then Derived::foo does not override Base::foo. Rather, Derived::foo hides Base::foo. The difference can be seen in the following example:
struct Base {
void foo() { std::cout << "Base::foo\n"; }
virtual void bar() { std::cout << "Base::bar\n"; }
};
struct Derived : Base {
void foo() { std::cout << "Derived::foo\n"; }
virtual void bar() { std::cout << "Derived::bar\n"; }
};
int main() {
Derived d;
Base* b = &d;
b->foo(); // calls Base::foo
b->bar(); // calls Derived::bar
}
(Derived::bar is implicitly virtual even if you don't use the virtual keyword, as long as it's signature is compatible to Base::bar.)
A qualified-id is either of the form X :: Y or just :: Y. The part before the :: specifies where we want to look up the identifier Y. In the first form, we look up X, then we look up Y from within X's context. In the second form, we look up Y in the global namespace.
An unqualified-id does not contain a ::, and therefore does not (itself) specify a context where to look up the name.
In an expression b->foo, both b and foo are unqualified-ids. b is looked up in the current context (which in the example above is the main function). We find the local variable Base* b. Because b->foo has the form of a class member access, we look up foo from the context of the type of b (or rather *b). So we look up foo from the context of Base. We will find the member function void foo() declared inside Base, which I'll refer to as Base::foo.
For foo, we're done now, and call Base::foo.
For b->bar, we first find Base::bar, but it is declared virtual. Because it is virtual, we perform a virtual dispatch. This will call the final function overrider in the class hierarchy of the type of the object b points to. Because b points to an object of type Derived, the final overrider is Derived::bar.
When looking up the name foo from Derived's context, we will find Derived::foo. This is why Derived::foo is said to hide Base::foo. Expressions such as d.foo() or, inside a member function of Derived, using simply foo() or this->foo(), will look up from the context of Derived.
When using a qualified-id, we explicitly state the context of where to look up a name. The expression Base::foo states that we want to look up the name foo from the context of Base (it can find functions that Base inherited, for example). Additionally, it disables virtual dispatch.
Therefore, d.Base::foo() will find Base::foo and call it; d.Base::bar() will find Base::bar and call it.
Fun fact: Pure virtual functions can have an implementation. They cannot be called via virtual dispatch, because they need to be overridden. However, you can still call their implementation (if they have one) by using a qualified-id.
#include <iostream>
struct Base {
virtual void foo() = 0;
};
void Base::foo() { std::cout << "look ma, I'm pure virtual!\n"; }
struct Derived : Base {
virtual void foo() { std::cout << "Derived::foo\n"; }
};
int main() {
Derived d;
d.foo(); // calls Derived::foo
d.Base::foo(); // calls Base::foo
}
Note that access-specifiers both of class members and base classes have an influence on whether or not you can use a qualified-id to call a base class's function on an object of a derived type.
For example:
#include <iostream>
struct Base {
public:
void public_fun() { std::cout << "Base::public_fun\n"; }
private:
void private_fun() { std::cout << "Base::private_fun\n"; }
};
struct Public_derived : public Base {
public:
void public_fun() { std::cout << "Public_derived::public_fun\n"; }
void private_fun() { std::cout << "Public_derived::private_fun\n"; }
};
struct Private_derived : private Base {
public:
void public_fun() { std::cout << "Private_derived::public_fun\n"; }
void private_fun() { std::cout << "Private_derived::private_fun\n"; }
};
int main() {
Public_derived p;
p.public_fun(); // allowed, calls Public_derived::public_fun
p.private_fun(); // allowed, calls Public_derived::public_fun
p.Base::public_fun(); // allowed, calls Base::public_fun
p.Base::private_fun(); // NOT allowed, tries to name Base::public_fun
Private_derived r;
r.Base::public_fun(); // NOT allowed, tries to call Base::public_fun
r.Base::private_fun(); // NOT allowed, tries to name Base::private_fun
}
Accessibility is orthogonal to name lookup. So name hiding does not have an influence on it (you can leave out public_fun and private_fun in the derived classes and get the same behaviour and errors for the qualified-id calls).
The error in p.Base::private_fun() is different from the error in r.Base::public_fun() by the way: The first one already fails to refer to the name Base::private_fun (because it's a private name). The second one fails to convert r from Private_derived& to Base& for the this-pointer (essentially). This is why the second one works from within Private_derived or a friend of Private_derived.
First of all Derived should inherit from Base.
class Derived : public Base{
That said
First of you can just not have foo in Derived
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
Second you can make Derived::foo call Base::foo.
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
public:
void foo(){ Base::foo(); }
^^^^^^^^^^
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
Third you can use qualified id of Base::foo
int main(){
Derived bar;
bar.Base::foo(); // calls Base::foo()
return 0;
}
Consider making foo() virtual in the first place.
class Base {
public:
virtual ~Base() = default;
virtual void foo() { … }
};
class Derived : public Base {
public:
virtual void foo() override { … }
};
However, this does the job:
int main() {
Derived bar;
bar.Base::foo();
return 0;
}
An important [additional] note: you will still have compilation errors if Name Hiding occurs.
In this case, either utilize the using keyword, or use the qualifer. Additionally, see this answer as well.
#include <iostream>
class Base{
public:
void foo(bool bOne, bool bTwo){std::cout<<"base"<<bOne<<bTwo;}
};
class Derived : public Base
{
public:
void foo(bool bOne){std::cout<<"derived"<<bOne;}
};
int main()
{
Derived bar;
//bar.foo(true,true); // error: derived func attempted
bar.foo(true); // no error: derived func
bar.Base::foo(true,true); // no error: base func, qualified
return 0;
}
I have a base class and the derived class. I need to access the protected member of the base class in the derived class. However, Eclipse does not allow me to access the data member as if it were a member of a derived class without caring that it was inherited. How do I do that?
class BaseClass {
protected:
static int a;
int b;
}
class DerivedClass: public BaseClass {
void SomeMethod {
a=10; // cannot resolve symbol
b=10; // cannot resolve symbol
BaseClass::a=10; //does not complain
BaseClass::b=10; //does not complain
}
}
I couldn't completely understand your question, but fixing the syntax errors, the following should work:
class BaseClass {
protected:
static int a;
int b;
}; // <-- Missing semicolon
int BaseClass::a = 0; // Define static member
class DerivedClass: public BaseClass {
void SomeMethod() { // <-- Missing ()
a=10;
b=10;
}
};// <-- Missing semicolon