0%

C++重写和虚函数对比

在子类中,可以声明一个和父类相同的函数,此时父类函数是否标记为virtual将会影响这一行为

当父类没有标记为virtual时,将子类转换为父类之后,执行的将会是父类方法

当父类标记为virtual时,将子类转换为父类之后,执行的将会是子类方法

核心:

  • 只有函数名和参数都相同才算相同的函数
  • 只用在父子类中相同函数,且该函数在父类中标记了virtual,才能通过子类调用

指针(Base *basep = ⊂)和引用(Base &base = sub;)

无virtual 有virtual
参数相同 子调用子方法
父调用父方法
子调用子方法
父调用子方法
参数不同 子调用子方法,无法调用父
父调用父方法,无法调用子
子调用子方法,无法调用父
父调用父方法,无法调用子

直接赋值(Base base = sub;)

无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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
class Base {
public:
void execute() { std::cout << "Base execute" << std::endl; }
virtual void vexecute() { std::cout << "Base virtual execute" << std::endl; }
void hexecute() { std::cout << "Base hide execute" << std::endl; }
virtual void vhexecute() { std::cout << "Base hide execute" << std::endl; }
};

class Sub : public Base {
public:
void execute() { std::cout << "Sub execute" << std::endl; }
void vexecute() { std::cout << "Sub virtual execute" << std::endl; }
void hexecute(int a) { std::cout << "Sub hide execute " << a << std::endl; }
void vhexecute(int a) { std::cout << "Sub hide execute " << a << std::endl; }
};

int main() {
{
Sub sub;
Base base = sub;
sub.execute(); // Sub execute
base.execute(); // Base execute
sub.vexecute(); // Sub virtual execute
base.vexecute(); // Base virtual execute
sub.hexecute(0); // Sub hide execute 0
// sub.hexecute(); no matching function for call to ‘Sub::hexecute()’
base.hexecute(); // Base hide execute
// base.hexecute(0); no matching function for call to ‘Base::hexecute(int)’
sub.vhexecute(0); // Sub hide execute 0
// sub.vhexecute(); no matching function for call to ‘Sub::vhexecute()’
base.vhexecute(); // Base hide execute
// base.vhexecute(0); no matching function for call to ‘Base::vhexecute(int)’
}{
Sub sub;
Base &base = sub;
sub.execute(); // Sub execute
base.execute(); // Base execute
sub.vexecute(); // Sub virtual execute
base.vexecute(); // Sub virtual execute
sub.hexecute(0); // Sub hide execute 0
// sub.hexecute(); no matching function for call to ‘Sub::hexecute()’
base.hexecute(); // Base hide execute
// base.hexecute(0); no matching function for call to ‘Base::hexecute(int)’
sub.vhexecute(0); // Sub hide execute 0
// sub.vhexecute(); no matching function for call to ‘Sub::vhexecute()’
base.vhexecute(); // Base hide execute
// base.vhexecute(0); no matching function for call to ‘Base::vhexecute(int)’
}{
Sub *subp = new Sub();
Base *basep = subp;
subp->execute(); // Sub execute
basep->execute(); // Base execute
subp->vexecute(); // Sub virtual execute
basep->vexecute(); // Sub virtual execute
subp->hexecute(0); // Sub hide execute 0
// subp->hexecute(); no matching function for call to ‘Sub::hexecute()’
basep->hexecute(); // Base hide execute
// basep->hexecute(0); no matching function for call to ‘Base::hexecute(int)’
subp->vhexecute(0); // Sub hide execute 0
// subp->vhexecute(); no matching function for call to ‘Sub::vhexecute()’
basep->vhexecute(); // Base hide execute
// basep->vhexecute(0); no matching function for call to ‘Base::vhexecute(int)’
delete subp;
}
return 0;
}