code 1
#include<iostream>
struct b
{
virtual void f1(void)
{
std::cout<<"b->f1n";
}
};
struct d:public b
{
void f1(int x)
{
std::cout<<"d->f1n";
}
};
int main()
{
b *p;
d d1;
p=(b*)&d1;
p->f1(4); // this gives error
}
[Error] no matching function for call to 'b::f1(int)'
代码2
#include<iostream>
struct b
{
virtual void f1(void)
{
std::cout<<"b->f1n";
}
};
struct d:public b
{
virtual void f1(int x)
{
std::cout<<"d->f1n";
}
};
int main()
{
b *p;
d d1;
p=(b*)&d1;
p->f1(4); // this gives error
}
输出:
[Error] no matching function for call to b::f1(int)
在第二个代码中,我只是在派生类fun中显式地写了virtual
。
对于这两种情况,编译器正在做早期绑定,因为它在基类中找到这些函数。表示派生类函数f1
不变为虚函数?
为什么在情形1中它不成为虚函数?在第二种情况下,我明确地写了virtual
关键字?
我还读到虚函数应该在覆盖的情况下使用over-hiding
虚函数背后的主要观点是,代码可以使用指向基类的指针来调用子类的方法,而无需知道子类的存在。
换句话说,你的代码实际上相当于:
#include<iostream>
struct b
{
virtual void f1(void)
{
std::cout<<"b->f1n";
}
};
// 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
}
所有编译器看到的是f1(void)
,它没有其他工作。这就是为什么它抱怨f1(4)
没有意义。
编译器碰巧能够在您的示例中看到d
的事实只是偶然的,并不影响任何事情。只要在类型为b
的指针上调用方法,就可以在任何b
的子类上调用方法,甚至是在还不存在的类上。但是,要使其工作,只能使用基类声明的方法。