Reputation: 21
I have been watching several videos, and I have come to know how virtual function calls are processed through late binding.
In early binding, for lines like ptr->func(...)
, the compiler reviews the data type for ptr
and looks in the corresponding class for the func(...)
definition.
While during late binding for virtual functions, ptr
address is accessed, and then the definition is looked up in the corresponding class.
If I am right about the mechanism I have just mentioned, then why does the following code produce an error?
class A{
public:
void func(){
}
};
class B: public A{
public:
virtual void f4(){
cout<<"Cunt"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Also, why does the below code produce the output base
instead of the output derived
?
class A{
public:
void f4(){
cout<<"base"<<endl;
}
};
class B: public A{
public:
virtual void f4(){
cout<<"derived"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Please help. Am I wrong about the mechanism?
Upvotes: 2
Views: 58
Reputation: 3506
In class A
, the function f4
should be defined as virtual
too:
class A {
public:
virtual void f4(){
std::cout << "base" << std::endl;
}
};
In your case, f4
is non-virtual function, due to non-virtual inheritance.
One more thing, derived virtual functions should be mark as override
, and the virtual
is not necessary:
class B : public A {
public:
void f4() override {
std::cout << "derived" << std::endl;
}
};
If you would try to mark f4
in B
as override
without making it virtual
in A
first, you would get the compilation error: error: ‘virtual void B::f4()’ marked ‘override’, but does not override
- which means that you won't be able to access it using A
class pointer.
Side note: read the following post: Why is "using namespace std;" considered bad practice?
Upvotes: 2
Reputation: 595402
In your first example, A
does not have a method named f4()
, so the call to ptr->f4()
is not valid.
In your second example, A::f4()
is not marked as virtual
, so the call to ptr->f4()
does not perform virtual dispatch, and so calls A::f4()
rather than B::f4()
.
The solution to both problems is the same - make f4()
be virtual in A
, and have B
override
it, eg:
class A{
public:
virtual void f4() {
cout << "base" << endl;
}
};
class B: public A{
public:
void f4() override {
cout << "derived" << endl;
}
};
int main(){
A* ptr;
B obj;
ptr = &obj;
ptr->f4();
return 0;
}
Upvotes: 1