In the example below I have a abstract class with pure virtual method (aka FUN1) and a normal method (aka FUN2).
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int,char**)
{
B b;
b.fun();
}
Why can't I call FUN2 on derived class? g++ gives an error:
main.cpp:19:8: error: no matching function for call to ‘B::fun()’
EDIT: note that Overload of pure virtual function question is different. I don't want to override methods.
This is how derived class member lookup works: in the expression b.fun(), fun is first looked up in the scope of class B, and the lookup finds B::fun(int). So it stops and never finds A::fun().
Relevant section of the standard is 10.2 [class.member.lookup]/4:
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in
C that satisfies the requirements of the language construct in which the lookup occurs. (...) If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.
To make the base class function directly accessible you can use a using declaration in the derived class, i.e. using A::fun;.
For methods that are implemented in the base class an alternative is sometimes to qualify to call, i.e. b.A::fun().
Try to add using A::fun; statement in B class :
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
using A::fun;
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int, char**)
{
B b;
b.fun();
b.fun(5);
}
Related
I found that 'using' keyword can be used in class definition.
according to https://en.cppreference.com/w/cpp/language/using_declaration, its used for member function is as follows:
If the name is the name of an overloaded member function of the base
class, all base class member functions with that name are introduced.
If the derived class already has a member with the same name,
parameter list, and qualifications, the derived class member hides or
overrides (doesn't conflict with) the member that is introduced from
the base class.
an example code is as follows:
#include <iostream>
struct B {
virtual void f(int) { std::cout << "B::f\n"; }
void g(char) { std::cout << "B::g\n"; }
void h(int) { std::cout << "B::h\n"; }
protected:
int m; // B::m is protected
typedef int value_type;
};
struct D : B {
using B::m; // D::m is public
using B::value_type; // D::value_type is public
using B::f;
void f(int) { std::cout << "D::f\n"; } // D::f(int) overrides B::f(int)
using B::g;
void g(int) { std::cout << "D::g\n"; } // both g(int) and g(char) are visible
// as members of D
using B::h;
void h(int) { std::cout << "D::h\n"; } // D::h(int) hides B::h(int)
};
int main()
{
D d;
B& b = d;
// b.m = 2; // error, B::m is protected
d.m = 1; // protected B::m is accessible as public D::m
b.f(1); // calls derived f()
d.f(1); // calls derived f()
d.g(1); // calls derived g(int)
d.g('a'); // calls base g(char)
b.h(1); // calls base h()
d.h(1); // calls derived h()
}
From the above code, I am not sure what is the difference, for instance
using B::f;
void f(int)
and
virtual void f(int)
Is there definite difference for using 'using' keyword in order to override class member function?
The wording from that article is unfortunate. They tried to fix it with the parenthetical, but…
This has nothing to do with virtual function overriding.
The two examples you give are different and unrelated.
One brings the base class f into scope, then chucks that away and introduces a new D::f function. (This will not be virtual unless B::f already was, per the normal rules).
The other declares a virtual D::f.
In the example below I have a abstract class with pure virtual method (aka FUN1) and a normal method (aka FUN2).
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int,char**)
{
B b;
b.fun();
}
Why can't I call FUN2 on derived class? g++ gives an error:
main.cpp:19:8: error: no matching function for call to ‘B::fun()’
EDIT: note that Overload of pure virtual function question is different. I don't want to override methods.
This is how derived class member lookup works: in the expression b.fun(), fun is first looked up in the scope of class B, and the lookup finds B::fun(int). So it stops and never finds A::fun().
Relevant section of the standard is 10.2 [class.member.lookup]/4:
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in
C that satisfies the requirements of the language construct in which the lookup occurs. (...) If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.
To make the base class function directly accessible you can use a using declaration in the derived class, i.e. using A::fun;.
For methods that are implemented in the base class an alternative is sometimes to qualify to call, i.e. b.A::fun().
Try to add using A::fun; statement in B class :
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
using A::fun;
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int, char**)
{
B b;
b.fun();
b.fun(5);
}
This code generates the following compilation error :
error: no matching function for call to 'C::print(int)'
can you help me figuring out the procedure that the compiler did to generate that error , (why it ignored the function in class B)
#include <iostream>
using std::cout;
class A {
public:
virtual void print ()
{ cout << "A";}
};
class B : public A {
int x;
virtual void print (int y)
{cout << x+y;}
};
class C : public B {
public:
void print ()
{cout << "C";}
};
int main () {
C* ptr = new C;
ptr->print (5);
}
Each subsequent definition of print hides its parent's. You need a using statement to unhide it:
class A {
public:
virtual void print ()
{ cout << "A";}
};
class B : public A {
public:
int x=1;
using A::print;
virtual void print (int y)
{cout << x+y;}
};
class C : public B {
public:
using B::print;
void print ()
{cout << "C";}
};
Demo
Your pointer is to C*, not B*. You wouldn't technically need to 'unhide' any print functions if your code looked like this:
B* ptr = new C;
However that this sort of hiding is not a particularly good idea... you should prefer overriding and just naming functions different things.
The compiler resolves overloads for the closest (class) type seen. So class C effectively hides the function signature inherited from class B.
To call for that specific function you have to qualify its scope explicitely:
ptr->B::print (5);
// ^^^
overloading means two things(eg functions) have same name in same space or scope like in same class but in overriding we rewrite the definition of function in different scope(class) but the name still remains same.
I have a base class inherited with many subclasses. I need to define a new signature for an abstract method, which is mostly a wrapper. I tried this
class B {
public:
virtual void f() = 0;
void f(string msg) { /* print msg and call f() */ }
};
class D : public B {
public:
void f() override { /* implementatation */}
};
int main() {
D d;
d.f("msg");
}
But it doesn't compile and give the following error
error: no matching function for call to 'D::f(string)
My questions are:
Why cannot D::f(string) be resolved?
Why does any of the following fix the problem?
renaming f(string) to f2(string) (ugly)
defining D::f(string x) { B::f(x)} (ugly as it has to be defined in every subclasses)
removing the abstract method, B::f() (not acceptable)
Any better solution?
The issue is that you hid B::f(std::string) here:
class D : public B {
public:
void f() override;
};
When you call D.f("msg"), name lookup will find the one f() in D and stop looking. We first find the candidate functions then perform overload resolution. Since that one happens to take no arguments, you get the compile error.
If you want to use the other overload of f, you need to bring it into D as well, like so:
class D : public B {
public:
using B::f;
void f() override;
};
Now we have D::f() (the overridden virtual function) and D::f(std::string ) (which we brought in from B).
An alternative, trivial solution would be to simply rename one or the other function so you don't have this problem to begin with.
Are you using the NVI idoims? Such as:
class B {
public:
virtual void f() = 0;
void f(string msg) {
/* print msg and call f() */
std::cout << msg;
f();
}
virtual ~B() {}
};
Then you should as far as possible try to call the non-virtual member function from the base class (by reference or pointer), such as:
D d;
B& b = d;
b.f("msg");
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;
}