第 1 章 迈向现代 C++

    在学习现代 C++ 之前,我们先了解一下从 C++11 开始,被弃用的主要特性:

    • 不再允许字符串字面值常量赋值给一个 char *。如果需要用字符串字面值常量赋值和初始化一个 char *,应该使用 const char * 或者 auto

      1. char *str = "hello world!"; // 将出现弃用警告
    • C++98 异常说明、 unexpected_handlerset_unexpected() 等相关特性被弃用,应该使用 noexcept

    • auto_ptr 被弃用,应使用 unique_ptr

    • register 关键字被弃用,可以使用但不再具备任何实际含义。

    • bool 类型的 ++ 操作被弃用。

    • 特别地,在最新的 C++17 标准中弃用了一些可以使用的 C 标准库,例如 <ccomplex><cstdalign><cstdbool><ctgmath>

    • ……等等

    还有一些其他诸如参数绑定(C++11 提供了 std::bindstd::function)、export 等特性也均被弃用。前面提到的这些特性如果你从未使用或者听说过,也请不要尝试去了解他们,应该向新标准靠拢,直接学习新特性。毕竟,技术是向前发展的。

    出于一些不可抗力、历史原因,我们不得不在 C++ 中使用一些 C 语言代码(甚至古老的 C 语言代码),例如 Linux 系统调用。在现代 C++ 出现之前,大部分人当谈及『C 与 C++ 的区别是什么』时,普遍除了回答面向对象的类特性、泛型编程的模板特性外,就没有其他的看法了,甚至直接回答『差不多』,也是大有人在。图 1.2 中的韦恩图大致上回答了 C 和 C++ 相关的兼容情况。

    从现在开始,你的脑子里应该树立『C++ 不是 C 的一个超集』这个观念(而且从一开始就不是,后面的中给出了 C++98 和 C99 之间的区别)。在编写 C++ 时,也应该尽可能的避免使用诸如 void* 之类的程序风格。而在不得不使用 C 时,应该注意使用 extern "C" 这种特性,将 C 语言的代码与 C++代码进行分离编译,再统一链接这种做法,例如:

    1. gcc -c foo.c

    编译出 foo.o 文件,再使用 clang++ 将 C++代码和 .o 文件链接起来(或者都编译为 .o 再统一链接):

    当然,你可以使用 Makefile 来编译上面的代码:

    1. C = gcc
    2. SOURCE_C = foo.c
    3. OBJECTS_C = foo.o
    4. SOURCE_CXX = 1.1.cpp
    5. LDFLAGS_COMMON = -std=c++2a
    6. all:
    7. $(C) -c $(SOURCE_C)
    8. $(CXX) $(SOURCE_CXX) $(OBJECTS_C) $(LDFLAGS_COMMON) -o $(TARGET)
    9. clean:
    10. rm -rf *.o $(TARGET)

    注意:Makefile 中的缩进是制表符而不是空格符,如果你直接复制这段代码到你的编辑器中,制表符可能会被自动替换掉,请自行确保在 Makefile 中的缩进是由制表符完成的。

    如果你还不知道 Makefile 的使用也没有关系,本教程中不会构建过于复杂的代码,简单的在命令行中使用 clang++ -std=c++2a 也可以阅读本书。

    如果你是首次接触现代 C++,那么你很可能还看不懂上面的那一小段代码,即:

    不必担心,本书的后续章节将为你介绍这一切。

    返回目录 | | 下一章 语言可用性强化

    本书系著,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议许可。项目中代码使用 MIT 协议开源,参见。