If I have a code like this:
struct A {
virtual void f(int) {}
virtual void f(void*) {}
};
struct B : public A {
void f(int) {}
};
struct C : public B {
void f(void*) {}
};
int main() {
C c;
c.f(1);
return 0;
}
I get an error that says that I am trying to do an invalid conversion from int to void*. Why can't compiler figure out that he has to call B::f, since both functions are declared as virtual?
After reading jalf's answer I went and reduced it even further. This one does not work as well. Not very intuitive.
struct A {
virtual void f(int) {}
};
struct B : public A {
void f(void*) {}
};
int main() {
B b;
b.f(1);
return 0;
}
The short answer is "because that's how overload resolution works in C++".
The compiler searches for functions F inside the C class, and if it finds any, it stops the search, and tries to pick a candidate among those. It only looks inside base classes if no matching functions were found in the derived class.
However, you can explicitly introduce the base class functions into the derived class' namespace:
struct C : public B {
void f(void*) {}
using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution
};
Or you could do this:
void main()
{
A *a = new C();
a->f(1); //This will call f(int) from B(Polymorphism)
}
Well I think first of all you did not understand what virtual mechanism or polymorhism. When the polymorphism is achieved only by using object pointers. I think you are new to c++. Without using object pointers then there is no meaning of polymorphism or virtual keyword use base class pointer and assign the desired derived class objects to it. Then call and try it.
Related
code 1
#include<iostream>
struct b
{
virtual void f1(void)
{
std::cout<<"b->f1\n";
}
};
struct d:public b
{
void f1(int x)
{
std::cout<<"d->f1\n";
}
};
int main()
{
b *p;
d d1;
p=(b*)&d1;
p->f1(4); // this gives error
}
Output
[Error] no matching function for call to 'b::f1(int)'
code 2
#include<iostream>
struct b
{
virtual void f1(void)
{
std::cout<<"b->f1\n";
}
};
struct d:public b
{
virtual void f1(int x)
{
std::cout<<"d->f1\n";
}
};
int main()
{
b *p;
d d1;
p=(b*)&d1;
p->f1(4); // this gives error
}
Output:
[Error] no matching function for call to b::f1(int)
In 2nd code, just I write explicitly virtual in derived class fun.
for both cases, compiler is doing early binding as it is finding these function in base class. Means the derived class function f1 is not becoming virtual ?
Why it is not becoming virtual function in case 1 ? and also in case 2 where I wrote explicitly virtual keyword ?
Also I read that virtual functions should use in just case of over-riding not in case of over-hiding, is that true ?
The main point behind virtual functions is that code can use a pointer to a base class to call methods of a child class without even knowing the child class exists.
In other words your code is effectively equivalent to this:
#include<iostream>
struct b
{
virtual void f1(void)
{
std::cout<<"b->f1\n";
}
};
// Implemented somewhere else entirely.
b* some_function_that_might_returns_a_d();
int main()
{
b *p;
p = some_function_that_might_returns_a_d();
p->f1(4); // this gives error
}
All the compiler sees is f1(void), it has nothing else to work with. That's why it complains that f1(4) makes no sense.
The fact that the compiler happens to be able to see d in your example is just incidental, and doesn't affect anything. As long as you are calling methods on a pointer of type b, you'll be able to invoke methods on any subclass of b, even on classes that don't exist yet. However, for this to work, only methods that have been declared by the base class can be used.
If we create an object pointer to base class class which points to its child class object then we use virtual key word for late binding
So.,in case of late binding,, our code goes like this :-
#include<iostream>
using namespace std;
struct A{
virtual void print() {
cout<<"function1";
}
};
struct B : public A{
void print(){
cout<<"function2";
}
};
struct C : public B{
void print(){
cout<<"function3";
}
};
int main(){
A* a = new C();
A* p = new B();
a->print();
p->print();
}
Now my question is : when we use virtual keyword in base class, all the functions of derived classes created in base class will become virtual.
In multilevel inheritance, is there any way so that we can stop the function of class c from being virtual??
Any way to break this chain of virtual functions ?
Sorry for any mistakes in question but i tried my best.. ☺️☺️
It is not possible to make a function that is already virtual be not virtual in a child class.
Virtuality is a property of the top-level base class, not the child classes. Once a method has been marked as virtual, and pointer to that class must use dynamic dispatch for that function when calling because the pointer could be pointing to a child class that has overridden the behaviour.
Consider this code:
A a;
B b;
C c;
A * ap = &a;
A * bp = &b;
A * cp = &c;
ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function3'
Here, the calls to print cannot tell which function to call at compile time, they absolutely must use dynamic dispatch.
However, you can make C::print behave like A::print
struct C : public B {
void print() {
A::print();
}
};
Which results in:
ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function1'
And if the behaviour of A::print() changes, C::print() mirrors those changes.
This will still be overridable though, unless you use the final keyword as outlined below.
Original answer:
I believe you are looking for the final specifier.
It's only available as of C++11 though.
To quote en.cppreference's page about the final specifier:
When used in a virtual function declaration or definition, final
ensures that the function is virtual and specifies that it may not be
overridden by derived classes. The program is ill-formed (a
compile-time error is generated) otherwise.
And a variation of the example they give, demonstrating the solution to your problem:
struct A
{
virtual void foo();
};
struct B : A
{
void foo() final; // B::foo is overridden and it is the final override
};
struct C : B
{
void foo() override; // Error: foo cannot be overridden as it's final in B
};
Forgive the obscure title. It's likely a duplicate but I couldn't find the correct phrase.
Consider the following inheritance hierarchy.
class A
{
public:
virtual void Foo(int i) { printf("A::Foo(int i)\n"); }
void Foo(int a, int b) { Foo(a + b); }
};
class B : public A
{
public:
void Foo(int i) override { printf("B::Foo(int i)\n"); }
};
class C : public B
{
public:
void Bar() { Foo(1, 2); } //error C2660: function does not take two arguments
};
A has two methods named Foo with a different number of parameters. Only one of them is virtual.
B overrides the virtual method.
C tries to call the non-virtual method and encounters an error.
Calling the method as A::Foo(1, 2) does work fine.
Question:
Why can't the compiler deduce that the correct method is found on A?
It seems odd we would have to explicitly add A:: in a call such as:
C c;
c.A::Foo(1, 2);
Because the member function named Foo is found at the class scope of B, and then name lookup stops, so the Foo in class A is not visible, and won't be considered for overload resolution, even if the version in class A is more appropriate. It is name hiding.
You can use using to introduce them into the same scope, and make overload resolution work as you expect. Such as:
class C : public B
{
using A::Foo;
using B::Foo;
public:
void Bar() { Foo(1, 2); }
};
See Unqualified name lookup
LIVE
Here is the code I'm talking about
#include <stdio.h>
#include <stdlib.h>
class A {
public:
void method() {printf("method A\n");}
virtual void parentMethod() { printf("parentMethod\n"); method(); }
};
class B : public A {
public:
void method() {printf("method B\n");}
};
int main(void) {
A a;
B b;
a.parentMethod();
b.parentMethod();
}
My question is why this is happening? Why when b.parentMethod() is called it doesn't print method B. I realize that it has something to do with method() being in A and B as well as being non-virtual, but I can't get my head around it. Would someone be able to explain this behaviour?
Any help is appreciated.
You code was missing a virtual keyword:
#include <stdio.h>
#include <stdlib.h>
class A {
public:
virtual void method() {printf("method A\n");} // virtual was missing
void parentMethod() { printf("parentMethod\n"); method(); } // unnecessary virtual keyword
};
class B : public A {
public:
void method() {printf("method B\n");}
};
int main(void) {
A a;
B b;
a.parentMethod();
b.parentMethod();
}
The definition in the most upper class must contain the virtual keyword. It is very logical if you think about it. In this case, when you call method() the compiler knows it has to do something more than with a normal function call immediately.
Otherwise, it would have to find and iterate on all the derived types to see if they contain a redefinition of method().
My question is why this is happening? Why when b.parentMethod() is called it doesn't print method B. I realize that it has something to
do with method() being in A and B as well as being non-virtual, but I
can't get my head around it. Would someone be able to explain this
behaviour?
C++ has two levels of indirection when it comes to classes/structures. You have your "plain functions" (including "overloaded", "lambdas", static, etc.) and you have your "virtual functions". First, let's explain "plain functions".
struct Foo {
void goo();
};
In this structure, goo is just a plain old functions. If you try to write it in C, this would be analogous to calling,
void goo(struct Foo *this);
Nothing magical, just a plain function with a "hidden" pointer (all c++ functions have that "hidden" this pointer passed to them). Now, let's re-implement this function in an inherited structure,
struct Goo : public Foo {
void goo();
};
...
Goo g;
g.goo();
Foo f;
f.goo();
Here, plain as day, g.goo() calls goo() in Goo structure, and f.goo() calls goo() in Foo structure. So, in C functions, this would be just,
void goo(struct Foo *this);
void goo(struct Goo *this);
provided C did parameter overloading. But still, just plain functions. Calling goo() in Foo object will call different function than calling goo() in Goo object. Compile time resolution only. But now, let's make our function "virtual"
struct Foo {
virtual void goo();
};
struct Goo : public Foo {
void goo(); // <- also virtual because Foo::goo() is virtual
// In C++11 you'll want to write
// void goo() override;
// which verifies that you spelled function name correctly
// and are not making *new* virtual functions! common error!!
};
...
Goo g;
g.goo();
Foo f;
f.goo();
What happens here is that Foo now contains a "virtual table". The compiler now creates a table of functions that maps location of "latest" goo() function. Namely, implicit Foo() constructor would do something like,
virt_table[goo_function_idx] = &Foo::goo;
and then the constructor in Goo() would update this table with,
virt_table[goo_function_idx] = &Goo::goo;
And then when you have,
Foo *f = new Goo();
f->goo();
what happens is akin to,
f->virt_table[goo_function_idx]();
The function location is looked up in the "virtual table", and that function is called. This means runtime resolution of functions, or polymorphism. And this is how Goo::goo() is called.
Without this table, the compiler can only call functions it knows for said object. So in your example, b.parentMethod() is looked up in the table and called. But method() is not part of that table, so only compile-time resolution is attempted. And since this pointer is A*, you get A::method called.
I hope this clears up the "virtual table" business - it's literally an internal lookup table, but only for functions marked as virtual!
PS. You may ask, "but the this pointer will get 'upcast' by the virtual table from Foo* to Goo*", and yes, it would. I'll leave it as an exercise for you to figure out why that would always be correct.
Well you are correct. This is happening because your method is not virtual. When you are calling it through the parent class, there is no way for it to know, that it was overloaded, so A::method is always called. If you mark method as virtual, then call to it will be routed through the class vtable, so A::method would be replaced by the B::method in the ascendant class.
virtual means that a method can be overridden in a subclass. I think you wanted method, not parentMethod, to be overridden for B. I've renamed parentMethod to foo to be less misleading.
#include <stdio.h>
#include <stdlib.h>
class A {
public:
virtual void method() {printf("method A\n");}
void foo() { printf("foo\n"); method(); }
};
class B : public A {
public:
void method() {printf("method B\n");}
};
int main(void) {
A a;
B b;
a.foo();
b.foo();
}
You'll see that this gives the expected output:
foo
method A
foo
method B
Here's the ideone.
I have a class that contains some functions (none are virtual) and 2 more classes publicly inherit that class. In both the sub classes I override the same function of the base class.
After creating objects of all three classes in main (located at the same file), I call the original function with the baseclass object and the overridden functions with the derivedclass objects.
I was expecting all 3 function calls to run the original function from the base class (since I didn't use 'virtual' anywhere in the code), but I actually get each version of that function working according to the class in which it was defined (3 different versions).
I have the classes Base & Derived as follows:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
in main:
int main()
{
Derived d;
d.foo();
}
I thought d.foo() should run Base::foo() if not using 'virtual'.
This is not "overriding"... and it doesn't need to be.
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
int main()
{
Derived d;
d.foo();
}
If I understand you correctly, then you were expecting this to execute Base::foo(), because the functions are not virtual and therefore one does not override the other.
But, here, you do not need virtual dispatch: the rules of inheritance simply state that you'll get the right function for the type of the object you run it on.
When you need virtual dispatch/overriding is a slightly different case: it's when you use indirection:
int main()
{
Base* ptr = new Derived();
ptr->foo();
delete ptr;
}
In the above snippet, the result will be that Base::foo() is called, because the expression ptr->foo() doesn't know that *ptr is really a Derived. All it knows is that ptr is a Base*.
This is where adding virtual (and, in doing so, making the one function override the other) makes magic happen.
You cannot override something that isn't virtual. Non-virtual member functions are dispatched statically based on the type of the instance object.
You could cheat by "overriding" a function by making it an inline function calling something indirectly. Something like (in C++03)
class Foo;
typedef int foo_sig_t (Foo&, std::string&);
class Foo {
foo_sig_t *funptr;
public:
int do_fun(std::string&s) { return funptr(*this,s); }
Foo (foo_sig_t* fun): funptr(fun) {};
~Foo () { funptr= NULL; };
// etc
};
class Bar : public Foo {
static int barfun(Bar&, std::string& s) {
std::cout << s << std::endl;
return (int) s.size();
};
public:
Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
// etc...
};
and later:
Bar b;
int x=b.do_fun("hello");
Officially this is not overloading a virtual function, but it looks very close to one. However, in my above Foo example each Foo instance has its own funptr, which is not necessarily shared by a class. But all Bar instances share the same funptr pointing to the same barfun.
BTW, using C++11 lambda anonymous functions (internally implemented as closures), that would be simpler and shorter.
Of course, virtual functions are in generally in fact implemented by a similar mechanism: objects (with some virtual stuff) implicitly start with a hidden field (perhaps "named" _vptr) giving the vtable (or virtual method table).