01.C++基础语法

333 阅读18分钟

01.基础语法

目录介绍
  • 1.1 C++快速介绍
    • 1.1.1 C++语言介绍
    • 1.1.2 C++的特点
    • 1.1.3 C++标准库
    • 1.1.4 C++应用领域
    • 1.1.5 C++的版本
  • 1.2 C++编译器
    • 1.2.1 编译器是什么
    • 1.2.2 GCC编译器
    • 1.2.3 Clang编译器
    • 1.2.4 MSVC编译器
    • 1.2.5 IDE开发环境
    • 1.2.6 在线编译器
  • 1.3 helloWorld
    • 1.3.1 第一个案例
    • 1.3.2 编译代码
    • 1.3.3 代码解读
  • 1.4 编译C++
    • 1.4.0 最简单编译
    • 1.4.1 编译单个文件
    • 1.4.2 编译多个文件
    • 1.4.3 指定C++标准
    • 1.4.4 启用优化
    • 1.4.5 生成调试信息
  • 1.5 多种注释使用
    • 1.5.1 单行注释
    • 1.5.2 多行注释
    • 1.5.3 文档注释工具
  • 1.6 命名空间
    • 1.6.1 命名空间概念
    • 1.6.2 定义命名空间
    • 1.6.3 访问命名空间成员
    • 1.6.4 嵌套命名空间
    • 1.6.5 匿名命名空间
    • 1.6.6 命名空间别名
    • 1.6.7 标准命名空间
    • 1.6.8 综合练习题
  • 1.7 头文件
    • 1.7.1 头文件扩展名
    • 1.7.2 头文件和实现类
    • 1.7.3 头文件保护
    • 1.7.4 模板类头文件
    • 1.7.5
  • 1.8 修饰符和标志符
    • 1.8.1 访问控制修饰符
    • 1.8.2 存储类型修饰符
    • 1.8.3 类型限定符
    • 1.8.4 函数修饰符
    • 1.8.5 类修饰符
    • 1.8.6 其他修饰符
    • 1.8.7 标志符
  • 1.9 关键字
    • 1.9.1 数据类型关键字
    • 1.9.2 存储类型关键字
    • 1.9.3 控制语句关键字
    • 1.9.4 类和对象关键字
    • 1.9.5 异常处理关键字
    • 1.9.6 类型转换关键字
    • 1.9.7 操作符相关关键字
    • 1.9.8 模板相关关键字
    • 1.9.9 命名空间相关关键字
    • 1.9.10 其他关键字

1.1 C++快速介绍

1.1.1 C++语言介绍

C++ 是一种通用的、高效的编程语言,广泛应用于系统编程、游戏开发、嵌入式系统、高性能计算等领域。

它是 C 语言 的扩展,同时支持面向过程编程和面向对象编程(OOP)。事实上,任何合法的 C 程序都是合法的 C++ 程序。

C++ 由 Bjarne Stroustrup 于 1980 年代初期在贝尔实验室开发,最初被称为“C with Classes”。

注意:使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。

1.1.2 C++的特点

  1. 高效性: C++ 直接编译为机器码,运行效率高。支持底层内存操作,适合开发高性能应用。
  2. 面向对象:支持类、对象、继承、多态等面向对象特性。
  3. 泛型编程:通过模板(template)支持泛型编程,提高代码复用性。
  4. 标准库:提供了丰富的标准库(如 STL,Standard Template Library),包括容器、算法、迭代器等。
  5. 兼容 C 语言:几乎完全兼容 C 语言,可以直接使用 C 语言的库和代码。
  6. 跨平台:支持多种操作系统(如 Windows、Linux、macOS)和硬件平台。

1.1.3 C++标准库

标准的 C++ 由三个重要部分组成:

  1. 核心语言,提供了所有构件块,包括变量、数据类型和常量,等等。
  2. C++ 标准库,提供了大量的函数,用于操作文件、字符串等。
  3. 标准模板库(STL),提供了大量的方法,用于操作数据结构等。

1.1.4 C++应用领域

  • 系统编程:操作系统、设备驱动程序、嵌入式系统。
  • 游戏开发:许多游戏引擎(如 Unreal Engine)使用 C++ 开发。
  • 高性能计算:科学计算、金融分析、人工智能。
  • 图形处理:图像处理、计算机视觉。
  • 网络编程:服务器开发、网络协议实现。
  • 桌面应用:使用 Qt、MFC 等框架开发跨平台 GUI 应用。

1.1.5 C++的版本

C++ 标准不断更新,主要版本包括:

  • C++98:第一个正式标准。
  • C++11:引入现代特性,如自动类型推导、Lambda 表达式。
  • C++14C++17C++20:逐步增强语言功能和标准库。

1.2 C++编译器

1.2.1 编译器是什么

C++ 编译器 是将 C++ 源代码转换为机器代码的工具,使程序能够在计算机上运行。

1.2.2 GCC编译器

GCC(GNU Compiler Collection):GCC是一个开源的编译器套件,包括C++编译器(g++)。它是许多Linux发行版的默认编译器,也可在其他操作系统上使用。

特点:开源、跨平台(支持 Linux、Windows、macOS 等)。支持最新的 C++ 标准(如 C++20)。性能优秀,广泛应用于开源项目。

1.2.3 Clang编译器

简介:Clang 是 LLVM 项目的一部分,专注于提供快速编译和清晰的错误信息。

特点: 开源、跨平台。编译速度快,错误信息友好。支持最新的 C++ 标准。

1.2.4 MSVC编译器

  • 简介:MSVC 是微软开发的 C++ 编译器,集成在 Visual Studio 中。
  • 特点:专为 Windows 平台优化。支持最新的 C++ 标准。提供强大的调试和开发工具。
  • 安装:通过 Visual Studio 安装。
  • 使用:在 Visual Studio 中创建项目并编译。

1.2.5 IDE开发环境

IDE 集成了编译器、编辑器、调试器等工具,提供更便捷的开发体验。以下是常用的 C++ IDE:

  • Visual Studio(Windows): 强大的调试工具,支持 MSVC 编译器。
  • Code::Blocks(跨平台):轻量级,支持多种编译器。
  • CLion(跨平台):JetBrains 开发的 C++ IDE,支持 CMake。
  • Xcode(macOS):苹果官方 IDE,支持 Clang 编译器。

1.2.6 在线编译器

如果你不想安装本地编译器,可以使用在线编译器快速测试代码:

Wandboxwandbox.org/

OnlineGDB【体验好,有代码自动补充】www.onlinegdb.com/

1.3 helloWorld

1.3.1 第一个案例

让我们看一段简单的代码,可以输出单词 Hello World。

#include <iostream>
using namespace std;

// main() 是程序开始执行的地方 是一个单行注释。
int main() {
    cout << "Hello world" << endl;
    return 0;
}

1.3.2 编译代码

通常我们使用 -o 选项指定可执行程序的文件名,以下实例生成一个 hello 的可执行文件:

$ g++ main.cpp -o hello
$ ./hello
hello world

1.3.3 代码解读

C++ 语言定义了一些头文件,这些头文件包含了程序中必需的或有用的信息。上面这段程序中,包含了头文件 。

下一行 using namespace std; 告诉编译器使用 std 命名空间。命名空间是 C++ 中一个相对新的概念。

下一行 // main() 是程序开始执行的地方 是一个单行注释。单行注释以 // 开头,在行末结束。

下一行 int main() 是主函数,程序从这里开始执行。

下一行 cout << "Hello World"; 会在屏幕上显示消息 "Hello World"。

下一行 return 0; 终止 main( )函数,并向调用进程返回值 0。

1.4 编译C++

1.4.0 最简单编译

最简单的编译方式:

$ g++ main.cpp

由于命令行中未指定可执行程序的文件名,编译器采用默认的 a.out。程序可以这样来运行:

$ ./a.out
hello world

1.4.1 编译单个文件

g++ program.cpp -o program
#如果是这样,那么默认会生成a.out
g++ program.cpp  
  • g++:调用 GCC 编译器。
  • program.cpp:源代码文件。
  • -o program:指定输出文件名为 program

1.4.2 编译多个文件

g++ main.cpp utils.cpp -o program
g++ Account.cpp Bank.cpp FileManager.cpp BankUserManager.cpp -o BankUserManager
  • 将多个源文件一起编译。

1.4.3 指定C++标准

g++ 有些系统默认是使用 C++98,我们可以指定使用 C++11 来编译 main.cpp 文件:

g++ -g -Wall -std=c++11 main.cpp
g++ -std=c++11 -o program program.cpp

-std=c++11:指定使用 C++11 标准。

1.4.4 启用优化

g++ -O2 -o program program.cpp
  • -O2:启用优化级别 2。

1.4.5 生成调试信息

g++ -g -o program program.cpp
  • -g:生成调试信息,便于使用 GDB 调试。

1.5 多种注释使用

在 C++ 中,注释 是用于解释代码的文本,编译器会忽略注释内容。注释对于提高代码的可读性和维护性非常重要,尤其是在团队协作或长期维护的项目中。

提示:编译器在编译代码时,会忽略注释的内容

1.5.1 单行注释

单行注释// 描述信息

通常放在一行代码的上方,或者一条语句的末尾,==对该行代码说明==

int main() {
    // 输出 Hello, World!
    cout << "Hello, World!" << endl; // 这是行尾注释
    return 0;
}

1.5.2 多行注释

多行注释/* 描述信息 */

通常放在一段代码的上方,==对该段代码做整体说明==

/*
这是一个简单的 C++ 程序
用于输出 Hello, World!
*/
int main() {
    cout << "Hello, World!" << endl;
    return 0;
}

1.5.3 文档注释工具

C++ 支持使用文档注释生成 API 文档,常用的工具包括:

1.6 命名空间

命名空间(Namespace) 是 C++ 中用于组织代码的机制,它可以避免命名冲突,尤其是在大型项目或使用第三方库时。命名空间将代码逻辑分组,并为其中的标识符(如变量、函数、类等)提供作用域。

1.6.1 命名空间概念

遇到问题:一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突。

场景例如:您可能会写一个名为 xyz() 的函数,在另一个可用的库中也存在一个相同的函数 xyz()。这样,编译器就无法判断您所使用的是哪一个 xyz() 函数。

解决办法:因此,引入了命名空间这个概念,可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上,命名空间就是定义了一个范围。

作用:防止命名冲突,将代码逻辑分组。语法

namespace 命名空间名 {
  // 变量、函数、类等
}

访问方式

  • 使用 命名空间名::标识符 访问命名空间中的成员。
  • 使用 using namespace 命名空间名; 引入整个命名空间。
  • 使用 using 命名空间名::标识符; 引入特定成员。

1.6.2 定义命名空间

namespace MyNamespace {
    int value = 42; // 变量
    void print() {  // 函数
        cout << "Hello from MyNamespace!" << endl;
    }
}

1.6.3 访问命名空间成员

#include <iostream>
using namespace std;

namespace MyNamespace {
    int value = 42;
    void print() {
        cout << "Hello from MyNamespace!" << endl;
    }
}

int main() {
    cout << MyNamespace::value << endl; // 访问变量
    MyNamespace::print();               // 调用函数
    return 0;
}

使用 using namespace

#include <iostream>
using namespace std;

namespace MyNamespace {
    int value = 42;
    void print() {
        cout << "Hello from MyNamespace!" << endl;
    }
}

using namespace MyNamespace; // 引入整个命名空间

int main() {
    cout << value << endl; // 直接访问变量
    print();               // 直接调用函数
    return 0;
}

使用 using 引入特定成员

#include <iostream>
using namespace std;

namespace MyNamespace {
    int value = 42;
    void print() {
        cout << "Hello from MyNamespace!" << endl;
    }
}

using MyNamespace::value; // 引入特定成员

int main() {
    cout << value << endl; // 直接访问变量
    MyNamespace::print();  // 仍需使用命名空间访问函数
    return 0;
}

1.6.4 嵌套命名空间

命名空间可以嵌套,形成层次结构。示例

namespace Outer {
    namespace Inner {
        void print() {
            cout << "Hello from Inner namespace!" << endl;
        }
    }
}

int main() {
    Outer::Inner::print(); // 访问嵌套命名空间
    return 0;
}

1.6.5 匿名命名空间

匿名命名空间用于定义仅在当前文件内可见的成员,类似于 static 关键字。示例

namespace {
    int value = 42; // 仅在当前文件内可见
}

int main() {
    cout << value << endl; // 直接访问
    return 0;
}

1.6.6 命名空间别名

可以为命名空间定义别名,简化代码。示例

namespace VeryLongNamespaceName {
    void print() {
        cout << "Hello!" << endl;
    }
}

namespace VLN = VeryLongNamespaceName; // 定义别名

int main() {
    VLN::print(); // 使用别名访问
    return 0;
}

1.6.7 标准命名空间

C++ 标准库的所有内容都定义在 std 命名空间中。

示例

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl; // 使用 std:: 访问
    return 0;
}

引入 std 命名空间

#include <iostream>
using namespace std; // 引入 std 命名空间

int main() {
    cout << "Hello, World!" << endl; // 直接访问
    return 0;
}

1.6.8 综合练习题

  1. 使用 namespace space名称 可以定义命名空间。通过命名空间可以调用所在区域函数
  2. 使用 using namespace space名称 可以通过该方式引入命名空间。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称。
  3. 嵌套的命名空间,命名空间可以嵌套,可以在一个命名空间中定义另一个命名空间。可以通过使用 :: 运算符来访问嵌套的命名空间中的成员。
//定义命名空间
namespace first_space {
    void fun() {
        cout << "Inside first_space" << endl;
    }
}
namespace second_space {
    void fun() {
        cout << "Inside second_space" << endl;
    }
}
void test1() {
    cout << "定义命名空间" << endl;
    // 调用第一个命名空间中的函数
    first_space::fun();
    // 调用第二个命名空间中的函数
    second_space::fun();
}

//using 指令
using namespace first_space;
//using 指令引入的名称遵循正常的范围规则。名称从使用 using 指令开始是可见的,直到该范围结束。此时,在范围以外定义的同名实体是隐藏的。
void test2() {
    cout << "using 指令" << endl;
    fun();
}

//嵌套的命名空间
namespace first_sp{
    void funSp() {
        cout << "Inside first_sp,逗比充1" << endl;
    }
    namespace second_sp {
        void funSp() {
            cout << "Inside second_sp,逗比充2" << endl;
        }
    }
}
using namespace first_sp::second_sp;


void test3() {
    cout << "嵌套的命名空间" << endl;
    // 调用第二个命名空间中的函数
    funSp();
}

int main() {
    test1();
    test2();
    test3();
    return 0;
}

1.7 头文件

在 C++ 中,头文件是用于声明类、函数、变量等的文件,通常以 .h.hpp 为扩展名。

1.7.1 头文件扩展名

  • .h:传统的 C 和 C++ 头文件扩展名,广泛使用。
  • .hpp:更现代的 C++ 头文件扩展名,通常用于强调该头文件是专门为 C++ 设计的。
  • .hh:在某些项目中也会使用,通常是 UNIX 或 Linux 社区的风格。
  • .tpp:用于模板类或函数的实现文件(通常与 .hpp 配合使用)。

1.7.2 头文件和实现类

头文件中只放类、函数、变量的声明,具体实现放在 .cpp 文件中。建议每个类单独一个头文件,便于维护和管理。 例如:

头文件声明:

// MyClass.h
class MyClass {
public:
  void doSomething();
};

实现类做具体实现:

// MyClass.cpp
#include "MyClass.h"
void MyClass::doSomething() {
  // 实现
}

1.7.3 头文件保护

使用头文件保护(#ifndef / #define#pragma once)防止重复包含。 例如:

// MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass {
public:
  void doSomething();
};

#endif // MYCLASS_H

1.8 修饰符和标志符

在 C++ 中,修饰符标志符是用于修饰变量、函数、类等的关键字或符号,它们可以改变对象的属性、行为或作用域。

1.8.1 访问控制修饰符

访问控制修饰符用于定义类成员的访问权限。

  • public:公有成员,任何地方都可以访问。
  • protected:受保护成员,只有类本身、派生类可以访问。
  • private:私有成员,只有类本身可以访问。

1.8.2 存储类型修饰符

存储类型修饰符用于定义变量的存储方式和生命周期。

  • auto:自动变量,编译器自动推导类型(C++11 引入)。
  • register:建议将变量存储在寄存器中(现代编译器通常忽略)。
  • static:静态变量,生命周期贯穿整个程序。
  • extern:声明变量在其他文件中定义。
  • mutable:允许在 const 对象中修改成员变量。

1.8.3 类型限定符

类型限定符用于修饰变量的行为或属性。

  • const:表示变量不可修改。
  • volatile:表示变量可能被外部修改,禁止编译器优化。
  • restrict:用于指针,表示指针是唯一访问内存的方式(C99 引入,C++ 中不常用)。

示例:

const int a = 10;          // 常量
volatile int b = 20;       // 易变变量

1.8.4 函数修饰符

函数修饰符用于限定函数的行为。

  • inline:建议编译器将函数内联。
  • virtual:表示函数是虚函数,可以被派生类重写。
  • override:明确表示重写基类的虚函数(C++11 引入)。
  • final:禁止派生类重写虚函数(C++11 引入)。
  • constexpr:表示函数可以在编译时求值(C++11 引入)。

示例:

class Base {
public:
    virtual void func() const; // 虚函数
};

class Derived : public Base {
public:
    void func() const override; // 重写基类虚函数
};

1.8.5 类修饰符

类修饰符用于限定类的行为。

  • final:禁止类被继承(C++11 引入)。
  • abstract:通过纯虚函数实现抽象类(没有直接的关键字,纯虚函数实现)。

示例:

class Base final { // 禁止继承
    // 类定义
};

1.8.6 其他修饰符

  • friend:允许非成员函数或其他类访问私有成员。
  • explicit:禁止构造函数的隐式转换(C++11 引入)。
  • noexcept:表示函数不会抛出异常(C++11 引入)。

示例:

class MyClass {
    friend void friendFunc(); // 友元函数
};

1.8.7 标志符

作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则

C++ 标识符是用来标识变量、函数、类、模块,或任何其他用户自定义项目的名称。

  • 标识符不能是关键字
  • 标识符只能由字母、数字、下划线组成
  • 第一个字符必须为字母或下划线
  • 标识符中字母区分大小写

建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读

有效标志符,一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。

无效标志符,C++ 标识符内不允许出现标点字符,比如 @、& 和 %。C++ 是区分大小写的编程语言。

1.9 关键字

C++ 中的关键字是语言保留的标识符,具有特定的含义和用途,不能用作变量名、函数名或其他用户定义的标识符。

C++ 的关键字包括从 C 继承的关键字以及 C++ 自己引入的关键字。

作用:关键字是C++中预先保留的单词(标识符)

  • 在定义变量或者常量时候,不要用关键字

C++关键字如下:

asmdoifreturntypedef
autodoubleinlineshorttypeid
booldynamic_castintsignedtypename
breakelselongsizeofunion
caseenummutablestaticunsigned
catchexplicitnamespacestatic_castusing
charexportnewstructvirtual
classexternoperatorswitchvoid
constfalseprivatetemplatevolatile
const_castfloatprotectedthiswchar_t
continueforpublicthrowwhile
defaultfriendregistertrue
deletegotoreinterpret_casttry

提示:在给变量或者常量起名称时候,不要用C++得关键字,否则会产生歧义。

1.9.1 数据类型关键字

这些关键字用于定义变量或函数的类型。

关键字含义
int整型
float浮点型
double双精度浮点型
char字符型
bool布尔型(truefalse
void无类型
wchar_t宽字符型
long长整型
short短整型
signed有符号类型
unsigned无符号类型

1.9.2 存储类型关键字

这些关键字用于定义变量的存储方式和生命周期。

关键字含义
auto自动类型推导(C++11 引入)
static静态变量
extern外部变量
register寄存器变量(建议存储在寄存器中,现代编译器通常忽略)
mutable允许在 const 对象中修改成员变量

1.9.3 控制语句关键字

这些关键字用于控制程序的执行流程。

关键字含义
if条件语句
else条件语句的分支
switch多分支选择语句
caseswitch 的分支
defaultswitch 的默认分支
for循环语句
while循环语句
do循环语句
break跳出循环或 switch 语句
continue跳过本次循环
return从函数返回
goto无条件跳转

1.9.4 类和对象关键字

这些关键字用于定义和操作类、对象和继承。

关键字含义
class定义类
struct定义结构体
union定义联合体
enum定义枚举
private私有访问权限
protected受保护访问权限
public公有访问权限
virtual虚函数
override重写基类虚函数(C++11 引入)
final禁止继承或重写(C++11 引入)
explicit禁止隐式转换(C++11 引入)
friend友元函数或友元类
this当前对象的指针
new动态分配内存
delete释放动态分配的内存

1.9.5 异常处理关键字

这些关键字用于处理异常。

关键字含义
try尝试执行一段代码
catch捕获异常
throw抛出异常
noexcept表示函数不会抛出异常(C++11 引入)

1.9.6 类型转换关键字

这些关键字用于进行显式类型转换。

关键字含义
static_cast静态类型转换
dynamic_cast动态类型转换
const_cast去掉或添加 const 限定符
reinterpret_cast重新解释类型

1.9.7 操作符相关关键字

这些关键字用于定义或重载操作符。

关键字含义
operator重载操作符
sizeof获取对象或类型的大小
typeid获取对象的类型信息
alignof获取类型的对齐要求(C++11 引入)

1.9.8 模板相关关键字

这些关键字用于定义和操作模板。

关键字含义
template定义模板
typename定义模板参数或别名
constexpr编译时常量(C++11 引入)
decltype推导表达式的类型(C++11 引入)

1.9.9 命名空间相关关键字

这些关键字用于定义和操作命名空间。

关键字含义
namespace定义命名空间
using使用命名空间或类型别名

1.9.10 其他关键字

这些关键字用于其他特殊用途。

关键字含义
nullptr空指针(C++11 引入)
static_assert静态断言(C++11 引入)
export模块导出(C++20 引入)
import模块导入(C++20 引入)
concept定义概念(C++20 引入)
co_await协程等待(C++20 引入)
co_yield协程生成值(C++20 引入)
co_return协程返回值(C++20 引入)