C++11 引入了许多新的特性,极大地提升了代码的安全性、可读性和性能。其中,finaloverride 关键字的引入为开发者提供了更强的控制与提示功能,而数值与字符串之间的便捷转换更是让常见的字符串操作更加简洁高效。


一、final 关键字的应用

1.1 什么是 final 关键字?

final 关键字用于限制某个类不能被继承,或者某个虚函数不能被重写。这样可以确保某些类或函数在继承体系中具有最终性,避免被派生类修改,提升了代码的安全性和设计的严谨性。

final 可以应用于两种情况:

  1. :表示该类不能被进一步继承。
  2. 虚函数:表示该虚函数在派生类中不能被重写。

1.2 final 关键字的用法示例

 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
class AA
{
public:
    virtual void test()
    {
        cout << "AA class..." << endl;
    }
};

class BB : public AA
{
public:
    void test() final   // 这个虚函数不能在其他派生类中被重写
    {
        cout << "BB class..." << endl;
    }
};

// 继承自 BB 的类
class CC : public BB
{
public:
    void test()  // 错误:BB 类中的 test() 方法已经用 final 限制,不能再重写
    {
        cout << "CC class..." << endl;
    }
};

在以上代码中,BB 类中的 test() 方法被标记为 final,这意味着任何继承 BB 的类都不能重写 test()。尝试在 CC 中重写该方法时会导致编译错误。

1.3 类的 final 限制

如果你想要创建一个不能被继承的类,可以将 final 关键字放在类名的后面:

1
2
3
4
class DD final   // 表示 DD 类不能被继承
{
    // 类的实现
};

任何尝试继承 DD 的类都会导致编译错误,这样的设计可以防止重要的类被无意修改。


二、override 关键字的应用

2.1 override 关键字的意义

override 关键字用于派生类中的虚函数,用来显式表明该函数是重写了基类的虚函数。虽然在没有 override 关键字时,派生类也可以重写基类的虚函数,但 override 的出现增强了代码的可读性和安全性,帮助编译器检查函数的重写是否正确。

如果派生类中的函数与基类的虚函数签名不匹配,而你使用了 override 关键字,编译器将报错。这有效地避免了由于不匹配导致的潜在错误。

2.2 override 关键字的用法示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class AA 
{
public:
    virtual void test()
    {
        cout << "AA class..." << endl;
    }
};

class BB : public AA
{
public:
    void test() override    // 明确指出这是在重写基类的虚函数
    {
        cout << "BB class..." << endl;
    }
};

在上面的例子中,BB 类中的 test() 函数重写了 AA 类中的虚函数。使用 override 关键字后,编译器可以进行检查,确保该重写是合法的。

2.3 为什么使用 override 很重要?

在没有 override 关键字的情况下,如果派生类的函数签名与基类的虚函数不匹配(如参数类型、数量等不同),编译器不会认为它是重写,而是认为这是一个新的函数。这种情况下,基类的虚函数仍然会被调用,这可能导致意外的行为。使用 override 可以避免这种错误。


三、数值类型与字符串之间的转换

C++11 提供了更简便的方式在数值类型和 string 类型之间进行转换。传统上,C++ 使用 sprintf()atoi() 等函数进行转换,但这些方法的安全性和可读性较差。在 C++11 中,提供了更为现代的函数接口,如 to_string()stoi() 等。

1. 数值转换为字符串

使用 to_string() 函数,可以将常见的数值类型转换为 string。这是一个非常直观的函数,可以避免复杂的格式化操作。

1
2
3
int num = 42;
string str = to_string(num);
cout << "转换后的字符串: " << str << endl;

to_string() 支持多种数值类型,包括 intlongfloatdouble 等。以下是常见的重载函数原型:

1
2
3
4
string to_string(int val);
string to_string(long val);
string to_string(float val);
string to_string(double val);

2. 字符串转换为数值

C++11 引入了 stoi()stol()stof() 等函数,用于将 string 类型转换为数值类型。这些函数非常方便,并且还可以通过可选参数来指定进制。

1
2
3
string str = "123";
int val = stoi(str);
cout << "转换后的整数: " << val << endl;

这些函数支持不同的数值类型和进制转换。函数原型如下:

1
2
3
int stoi(const string& str, size_t* pos = nullptr, int base = 10);
float stof(const string& str, size_t* pos = nullptr);
double stod(const string& str, size_t* pos = nullptr);

在转换过程中,如果字符串中包含无法转换的部分,可以通过 pos 参数获取解析停止的位置。

1
2
3
4
string str = "123abc";
size_t pos;
int val = stoi(str, &pos);
cout << "转换的整数: " << val << ", 停止位置: " << pos << endl;

输出:

1
转换的整数: 123, 停止位置: 3

在这个例子中,stoi 成功解析了前 3 个字符为整数 123,并在遇到无法解析的字符 a 时停止。


四、总结

C++11 引入的 finaloverride 关键字为类设计提供了更强的控制与安全性。使用 final 可以防止类或函数的进一步继承或重写,而 override 则为虚函数的重写提供了显式的编译器检查,极大地减少了潜在的编程错误。

此外,C++11 提供了更简洁的数值与字符串之间的转换方式,通过 to_string()stoi() 等函数,开发者可以轻松地在不同数据类型之间进行转换,提升了代码的可读性和安全性。