C++理论梳理10——部分Apollo代码关键字

final

C++11引入了关键字final,按官方的标准是该关键字是用来标识虚函数不能在子类中被覆盖(override),或一个类不能被继承。用法如下:

struct Base
{
    virtual void foo();
};

struct A : Base
{
    void foo() final; // Base::foo 被覆盖而 A::foo 是最终覆盖函数
    void bar() final; // 错误:非虚函数不能被覆盖或是 final
};

struct B final : A // struct B 为 final
{
    void foo() override; // 错误:foo 不能被覆盖,因为它在 A 中是 final
};

struct C : B // 错误:B 为 final
{
};

override

该关键字和虚函数密切相关,从字面意思上,就是覆盖的意思,实际上在C++中它是覆盖了一个方法并且对其重写,从而达到不同的作用。在我们C++编程过程中,最熟悉的就是对接口方法的实现(详见《C++理论梳理9——类之间的关系》),在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。还有一个典型应用就是在继承中也可能会在子类覆盖父类的方法。

下面给个好例子:
我们的意图是在子类Derived1与Derived2分别重载父类Base::print(void),在我们下面的代码中有没有发现什么问题呢?

class Base {
public:
    virtual void print(void){...}
};
class Derived1 : public Base {
public:
    void print(void){...}
};
class Derived2 : public Base {
public:
    void Print(void){...}	// 问题在这里
};

额…,原来因为不小心,在Derived2中将print误输入为Print,(注意其中的字母p的大小写),关键问题是编译器完全可以正确的编译上面的代码,这是一个很难发现的错误。

问题来了: 如何简单直接的向编译器表明意图,我就是要重载Base::print(void)呢?如果我写错了字母,你(指代编译器)要直接告诉我错误,或者一个警告也行?

答: override关键字可以做这件事情。

代码修改如下:

class Base {
public:
    virtual void print(void){...}
};
class Derived1 : public Base {
public:
    void print(void) override {...}
};
class Derived2 : public Base {
public:
    void Print(void) override {...}
};

当编译器看到上面代码的时候就开始很不爽了,编译器开始抱怨了,你通过 “override” 告诉我 "Derived2::Print(void)是要重载父类的某个函数,可是我根本没有在父类中找到 "Print(void)"函数,编译器直接丢出个错误,然后甩膀子不干了。

总结:override用于直接明了的告诉编译器该函数用于重载父类的某个虚函数

常见符号

在学习C++的过程中我们经常会用到.和::和:和->,在此整理一下这些常用符号的区别。

  1. A.B则A为对象或者结构体;
  2. A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针;
  3. ::是作用域运算符,A::B表示作用域A中的名称B,A可以是名字空间、类、结构;
  4. :一般用来表示继承。

参考

C++ override使用详解
C++中的 “override”
C++中的.和::和:和->的区别

你可能感兴趣的:(自动驾驶软件开发,c++,自动驾驶,planning,Apollo)