关于虚函数virtual

只有虚函数才能使你在仅用一个指针进行调用时,确保访问到期望的方法。非虚函数就没有这个特性。

见代码效果: 区别只在于有没有virtual

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream> 
using namespace std;

class Bus
{
int number;
protected:
int getNumber() const {
return number;
}
void setNumber(int number)
{
this->number = number;
}
public:
Bus(){}
Bus(int number) {
this->number = number;
}
virtual void print() const {
cout << "No. " << number << " bus." << endl;
}
};

class YellowBus : public Bus
{
public:
YellowBus(int number) {
setNumber(number);
}
void print() const {
cout << "No." << getNumber() << " yellow bus." << endl;
}
};

void print1(const Bus & bus) {
bus.print();
}

void print2(const Bus bus) {
bus.print();
}

int main() {
int number;
cin >> number;
YellowBus yellow(number);
print1(yellow);
print2(yellow);
}
1
2
3
4
100

No. 100 yellow bus.
No. 100 bus.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream> 
using namespace std;

class Bus
{
int number;
protected:
int getNumber() const {
return number;
}
void setNumber(int number)
{
this->number = number;
}
public:
Bus(){}
Bus(int number) {
this->number = number;
}
void print() const {
cout << "No. " << number << " bus." << endl;
}
};

class YellowBus : public Bus
{
public:
YellowBus(int number) {
setNumber(number);
}
void print() const {
cout << "No." << getNumber() << " yellow bus." << endl;
}
};

void print1(const Bus & bus) {
bus.print();
}

void print2(const Bus bus) {
bus.print();
}

int main() {
int number;
cin >> number;
YellowBus yellow(number);
print1(yellow);
print2(yellow);
}
1
2
3
4
100

No. 100 bus.
No. 100 bus.
  1. 那么virtual函数应该在什么情况下用呢?
  • virtual 函数应该在某个类的某个函数需要多态性的情况下使用
  • 还有一个使用场景是若类存在派生,那么析构函数必须是virtual的,否则可能会导致资源泄露。
  • 而非 virtual 函数,能够确保你使用基类指针就一定调用基类实现,防止派生类无意中覆盖。
  1. 是不是用virtual的函数都能用非virtual的函数替代?
  • 正相反,若在开发过程中做了良好约定,所有的非virtual函数都能用virtual函数代替。
  • 由于调用virtual函数多了一次查vtable的动作,可能导致(微不可查)的性能损失。不过这并非是不可接受的,某些框架例如Qt,大部分类都是采用这种哲学进行设计,并没有什么问题。
  • 有些语言比如 python 就是这么干的,程序员自己去保障覆盖问题。
  1. 那么是不是virtual没什么用呢?
  • 若是不考虑效率和强行避免覆写问题,其实非virtual函数才是没什么用的。
Donate? comment?