TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

override final

参考

虚函数

函数重载有以下要求:

  • 基类中的函数必须是虚函数
  • 基类和派生类中的函数名字必须完全相同(析构函数例外)、
  • 基类和派生类中的函数形参型别必须完全相同
  • 基类和派生类中的函数常量性必须完全相同
  • 基类和派生类中的函数返回值和异常规格必须兼容

c++11又多了一条:

  • 基类和派生类中的函数引用饰词必须完全相同

引用饰词

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
#include <iostream>
using namespace std;

class mydata
{
public:
mydata() { cout << "constructor" << endl; }
~mydata() { cout << "destructor" << endl; }
mydata(mydata && param) { cout << "move constructor" << endl; }
mydata(mydata & param) { cout << "copy constructor" << endl; }
mydata operator =(mydata && param) { cout << "move operator = " << endl; }
};

class myclass
{
public:
mydata _m;

myclass():_m()
{

}

mydata& data() & //*this是左值才调用
{
cout << "--data() &" << endl;
return this->_m;
}

mydata data() && //*this是右值才调用
{
cout << "--data() &&" << endl;
return std::move(this->_m);
}
};

myclass makemyclass()
{
return myclass();
}

int main() {

myclass my;
auto a1 = my.data();
auto a2 = makemyclass().data();

}

override

c++11允许在派生类的成员函数末尾添加override,表明派生类将要重写该函数,编译器会校验重写的规则,避免了一些隐晦的含义。

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
68
69
70
71
72
#include <iostream>
using namespace std;

class base {
public:
virtual void func1() const{
cout << "base: virtual void func1() const" << endl;
}
virtual void func2(int x){
cout << "base: virtual void func2(int x)" << endl;
}
virtual void func3() & {
cout << "base: virtual void func3() &" << endl;
}
void func4() const {
cout << "base: void func4() const" << endl;
}
};

class derived : public base {
public:
virtual void func1() {
cout << "derived: virtual void func1()" << endl;
}
virtual void func2(unsigned int x) {
cout << "derived: virtual void func2(unsigned int x)" << endl;
}
virtual void func3() && {
cout << "derived: virtual void func3() &&" << endl;
}
void func4() const {
cout << "derived: void func4() const" << endl;
}
};

#if 0
class derived2 : public base {
public:
virtual void func1() override; //error
virtual void func2(unsigned int x) override; //error
virtual void func3() && override; //error
void func4() const override; //error
};
#endif

class derived3 : public base {
public:
virtual void func1() const override; //ok
virtual void func2(int x) override; //ok
virtual void func3() & override; //ok
//void func4() const override; //需要修改基类
};

derived makederived()
{
return derived();
}

int main() {
derived der;
base *bas = &der;

bas->func1(); //base: virtual void func1() const

unsigned int x = 0;
bas->func2(x); //base : virtual void func2(int x)

bas->func3(); //base : virtual void func3() &

bas->func4(); //base : void func4() const
}

final

  • final跟在类定义后面,表示该类不能被继承:class test1 final
  • final不能修饰非虚函数
  • final在基类的虚函数后面,表示派生类不可以重载该函数
  • final在派生类的虚函数后面,表示派生类的其他派生类不能重载该派生类的此函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Base
{
virtual void foo();
};

struct A : Base
{
//#a
void foo() final; // Base::foo is overridden and A::foo is the final override
void bar() final; // Error: bar cannot be final as it is non-virtual
};

struct B final : A // struct B is final
{
void foo() override; // Error: foo cannot be overridden as it is final in A
};

struct C : B // Error: B is final
{
};

对于上面#a的解释:

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
#include <iostream>
using namespace std;

struct Base
{
virtual void foo()
{
cout << "base: foo()" << endl;
}
};

struct A : Base
{
void foo() final // Base::foo is overridden and A::foo is the final override
{
cout << "A: foo()" << endl;
}
//void bar() final; // Error: bar cannot be final as it is non-virtual
};

int main() {
A a;
Base *p = &a;
p->foo();
}
A: foo()

总结

  • override与final都不是语言关键字(keyword),只有在特定的位置才有特别含意,其他地方仍旧可以作为一般指示字(identifier)使用。override仅出现在成员函数的末尾才有意义。其他地方使用意义就变了:
1
2
3
4
void override(void)
{
cout << "override" << endl;
}
  • 为意在重写的函数添加override
  • 成员函数引用饰词使得对于左值和右值对象(*this)的处理能够区分开来

ending

2020071203_lit.jpg

----------- ending -----------