关于虚函数的说明如下:
1. 因为虚函数只对类的对象进行调用,所以不能将全局或静态函数声明为虚拟函数。
2. 可以使用virtual关键字在派生类中声明这是一个覆盖基类某个函数的虚函数,但这不是必须的;因为基类的虚函数被子类覆盖后,子类的函数一定是虚函数。
3. 基类中的虚拟函数必须被定义,除非它们是用 pure-specifier 声明的纯虚函数。(关于纯虚函数的更多信息,请参阅抽象类)。
4. 虚函数调用机制可以通过使用范围解析操作符(::)明确限定函数名称来指定具体调用哪个类的函数。
5. 在类的外面定义一个类的虚函数时,不能再添加virtual关键字,否则会编译报错。
6. 虚函数的访问权限只由调用的对象的声明类型来决定。
7. 虚函数调用是按照对象的声明类型是否是虚函数,而不是按照实际对象类型来判断。
第二点的例子说明:
#include <cstdio>
class A {
public:
virtual void func(){printf("func A.\n");}
};
class B: public A {
public:
void func(){printf("func B.\n");}
};
int main()
{
A a;
B b;
A * p;
p = &a;
p->func();
p = &b;
p->func();
return 0;
}
输出:
func A.
func B.
虽然子类没有使用virtual关键字,但还是虚函数。
第四点例子说明:
#include <cstdio>
class A {
public:
virtual void func(){printf("func A.\n");}
};
class B: public A {
public:
void func(){printf("func B.\n");}
};
int main()
{
A a;
B b;
A * p;
p = &a;
p->A::func();
p = &b;
p->A::func();
return 0;
}
输出:
func A.
func A.
直接指定调用,就不再和虚函数相关。
而是根据当前对象的声明类型,直接访问此类或其父类的成员函数或成员变量。还有外部访问当然需要public权限。
第五点例子:
class A{
public:
virtual void func();
};
// virtual void A::func() 会报错
void A::func()
{
}
在类的外面定义其成员函数,不能加virtual关键字,否则编译报错。
第六点例子:
#include <cstdio>
class A {
public:
virtual void func(){printf("func A.\n");}
};
class B: public A {
private:
virtual void func(){printf("func B.\n");}
};
int main()
{
A a;
B b;
A * p;
p = &a;
p->func();
p = &b;
p->func();
return 0;
}
输出:
func A.
func B.
子类的虚函数是private访问权限,当调用时还是按照父类的访问规则,仍能够public访问。
第七点例子:
#include <cstdio>
class A {
public:
void func(){printf("func A.\n");}
};
class B: public A {
public:
virtual void func(){printf("func B.\n");}
};
class C: public B {
public:
virtual void func(){printf("func C.\n");}
};
int main()
{
A a;
B b;
C c;
A * pa;
B * pb;
pa = &a;
pa->func();
pa = &b;
pa->func();
pa = &c;
pa->func();
pb = &b;
pb->func();
pb = &c;
pb->func();
return 0;
}
输出:
func A.
func A.
func A.
func B.
func C.
当使用没有虚函数的基类的指针时,即使其子类将此函数覆盖为虚函数,调用时则按照基类的规则而不是虚函数来调用。
相关文摘:
Because virtual functions are called only for objects of class types, you cannot declare global or static functions as virtual.
The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary; overrides of virtual functions are always virtual.
Virtual functions in a base class must be defined unless they are declared using the pure-specifier. (For more information about pure virtual functions, see Abstract Classes.)
The virtual function-call mechanism can be suppressed by explicitly qualifying the function name using the scope-resolution operator (::). Consider the earlier example involving the Account class.
Remember that, when you are trying to give implementation of a virtual member function, you cannot mark virtual again outside the class definition.
参考: