C++的常用关键字包括:auto、decltype、bool、throw、try、catch、class、constexpr、new、delete、const_cast、static_cast、dynamic_cast、reinterpret_cast、explicit、export、friend、mutable、using、namespace、noexcept、nullptr、operator、private、protected、public、static_assert、template、typename、this、thread_local、typeid、virtual等。我们结合代码示例来介绍各个关键字。

目录

1、auto自动推断变量

2、decltype推断变量类型

3、bool布尔变量

4、throw/try/catch异常处理

5、class类与对象

6、constexpr常量表达式

7、new与delete管理对象

8、类型转换

9、explicit显式调用

10、export全局引用

11、friend友元函数

12、mutable可变变量

13、namespace命名空间

14、noexcept禁止异常

15、nullptr空指针

16、private、protected和public

17、typeid获取类型信息

18、operator重载操作符

19、template模板

20、this指针

21、thread_local线程私有

22、virtual虚函数


1、auto自动推断变量

auto根据变量初始化来推断变量类型。示例如下:

auto array = new int[8];

2、decltype推断变量类型

与auto不同的是,decltype是根据表达式来推断变量类型。语法格式如下:

decltype(expression) var;

表达式包括:变量、运算、函数等,示例如下:

long add() {
    return 0;
}

void hello() {
    int a = 2;
    decltype(a) b; // b为int类型
    decltype(add()) c; // c为long类型
}

3、bool布尔变量

bool关键字表示布尔变量,只有true或false两种变量值。

4、throw/try/catch异常处理

使用关键字throw抛出异常,使用try/catch来捕获异常。示例代码如下:

    try {
        std::string msg("This is a test exception");
        throw msg;
    } catch (const std::string &e) {
        printf("exception=%s", e.c_str());
    }

5、class类与对象

C++的类与java类相似,都是面向对象编程。类的声明示例如下:

#include <string>

class Person {
private:
    int m_age;
    std::string m_name;
public:
    void setAge(int age);
    int getAge();
    void setName(const std::string &name);
    std::string getName();
};

对应的类实现如下:

#include "Person.h"

void Person::setAge(int age) {
    m_age = age;
}

int Person::getAge() {
    return m_age;
}

void Person::setName(const std::string &name) {
    m_name = name;
}

std::string Person::getName() {
    return m_name;
}

创建Person类的对象实例:

    auto person = new Person();
    person->setAge(10);
    person->setName("frank");
    printf("name=%s, age=%d", person->getName().c_str(), person->getAge());

6、constexpr常量表达式

constexpr只能修饰带有return的函数。在C++20增加了consteval修饰常量表达式,不同的是,在编译期确定参数类型。示例如下:

constexpr int hello(int a, int b) {
    return a + b;
}

另外,函数体内不能有赋值运算,否则有如下报错:

subexpression not valid in a constant expression

7、new与delete管理对象

在C++提供关键字new来创建对象,delete释放对象。在C语言是用库函数malloc来申请内存,free来释放内存。要注意的是,释放数组需要加上[]。示例如下:

    // 创建对象
    auto person = new Person();
    // 释放对象
    delete person;
    // 创建数组
    auto array = new int[8];
    // 释放数组
    delete[] array;

8、类型转换

C++提供const_cast、static_cast、dynamic_cast和reinterpret_cast四种类型转换,如下表所示:

const_cast用于修改const属性,接受指针或引用类型
static_cast用于基本类型转换
dynamic_cast用于有继承关系的类指针转换,支持类型检查
reinterpret_cast用于指针类型转换

类型转换的示例代码如下:

    // const_cast用于const属性
    const int a = 10;
    int &b = const_cast<int &> (a);
    // static_cast基本类型转换
    float x = 10.5f;
    int y = static_cast<int> (x);
    // dynamic_cast用于子类与父类转换
    SuperMan *superman = new SuperMan();
    superman->setAge(100);
    Person *person = dynamic_cast<Person*> (superman);
    // reinterpret_cast用于指针类型转换
    void *data = (void *) "hello";
    char *new_data = reinterpret_cast<char *> (data);

9、explicit显式调用

explicit用于修饰单参数的构造函数,被修饰的构造函数只能被显式调用,不能被隐式调用。示例如下:

class Person {
private:
    int m_age;
public:
    explicit Person(int age);
};

10、export全局引用

C语言有extern关键字用于声明全局变量,但是C++的模板没法用extern修饰。因此,提供export修饰在头文件声明的模板类或模板函数,其他源文件只要引用该头文件即可使用模板类或模板函数。

11、friend友元函数

friend关键字把函数声明为友元函数。声明函数为外部类的友元函数后,外部类可以通过友元函数访问该类的私有成员。示例代码如下:

class Pointer;

class Calculator {
public:
    Pointer* add(Pointer &a, Pointer &b);
};

class Pointer {
    // 声明为Calculator的友元函数
    friend Pointer* Calculator::add(Pointer &a, Pointer &b);
private:
    int m_x;
    int m_y;
public:
    Pointer(int x, int y);
};

// Calculator访问Pointer的私有成员,通过对象访问
Pointer* Calculator::add(Pointer &a, Pointer &b) {
    return new Pointer(a.m_x + b.m_x, a.m_y + b.m_y);
}

12、mutable可变变量

mutable用于且只能修饰类的成员变量,与const修饰常量相反。比如,constexpr修饰的常量表达式不允许修改成员变量,而成员变量添加mutable修饰符后可修改。示例如下:

class Person {
    
private:
    mutable int m_age; 
public:
    explicit Person(int age);
    constexpr int getAge();

};

constexpr int Person::getAge() {
    m_age += 10; // 修改成员变量
    return m_age;
}

非成员变量使用mutable修饰符会报错如下:

'mutable' can only be applied to member variable

13、namespace命名空间

命名空间用于模块隔离,避免模块之间命名冲突。示例代码如下:

namespace Learning {
    class Person {

    private:
        std::string m_name;
    public:
        void setName(const std::string &name);
        std::string getName();
    };
}

使用using引用命名空间,需要注意的是遵循最小原则。示例如下:

    // 直接命名空间引用
    Learning::Person *person1 = new Learning::Person();
    // 引入命名空间
    using namespace Learning;
    Person *person2 = new Person();

14、noexcept禁止异常

使用noexcept修饰函数禁止抛出异常,防止错误扩散。示例如下:

std::string getName() noexcept;

15、nullptr空指针

在C语言使用NULL表示空指针,java使用null表示空指针,Object-C使用nil表示空指针。当然,今天的主角是C++,它使用nullptr表示空指针。

16、private、protected和public

与java类似,C++提供private、protected和public访问修饰符,可以修饰类、函数、变量。三者对比如下:

private类内部访问
proteted有继承关系的类可访问
public类外部都可以访问

17、typeid获取类型信息

typeid用于获取类型信息的操作符,使用示例如下:

typeid(a).name()

基本类型对应的类型信息如下表:

基本类型类型信息
inti
charc
shorts
doubled
floatf
longl

18、operator重载操作符

在C++中,字符串能够进行加法运算或比较运算,是因为使用operator重载。我们来看下重载加法运算的示例:

class Point {

private:
    int m_x;
    int m_y;
public:
    Point(int x, int y);
    int getX();
    int getY();
    // 重载加法运算
    Point operator +(const Point &p) const {
        return {m_x + p.m_x, m_y + p.m_y};
    }
};

然后调用Point类的加法:

    Point p1(1, 2);
    Point p2(2, 3);
    Point point = p1 + p2;
    printf("point.x=%d, point.y=%d\n", point.getX(), point.getY());

19、template模板

template可以用于模板类或模板方法,支持不同数据类型的方法复用。示例如下:

template <typename T>
T add(T a, T b) {
    return a + b;
}

然后分别是int类型与float类型的加法运算:

    int a = 2, b = 3;
    int result1 = add(a, b);
    printf("int add=%d\n", result1);
    float c = 2.5f, d = 3.5f;
    float result2 = add(c, d);
    printf("float add=%f\n", result2);

20、this指针

this指针在类内部使用,可以访问类的所有成员。示例如下:

Point::Point(int x, int y) {
    this->m_x = x;
    this->m_y = y;
}

21、thread_local线程私有

thread_local用于表示线程私有变量,即每个线程都会存储一个变量的值,线程之间互不共享,是C++提供的存储期关键字。与thread_local类似的存储期关键字还有:auto、register、static、extern,各个关键字对比如下:

auto自动存储期
register自动存储期,位于寄存器
static静态存储期
extern程序存储期,全局使用
thread_local线程存储期,线程私有

22、virtual虚函数

虚函数是C++的多态机制,使用virtual关键字声明,允许通过基类指针访问基类与派生类的同名函数。基类的析构函数需要声明为虚函数,否则调用不到派生类的析构函数,导致内存泄漏。示例代码如下:

class Animal {
protected:
    std::string m_name;
public:
    Animal(const std::string &name);
    // 析构函数声明为虚函数
    virtual ~Animal();
};

class Cat : public Animal {
public:
    Cat(const std::string &name);
    ~Cat();
};

基类与派生类的实现:

Animal::Animal(const std::string &name) {
    m_name = name;
}

Animal::~Animal() noexcept {
    printf("Animal release\n");
}

Cat::Cat(const std::string &name) : Animal(name) {
    m_name = name;
}

Cat::~Cat() noexcept {
    printf("Cat release\n");
}

测试代码,创建Cat类,然后释放:

    Animal *cat = new Cat("cat");
    delete cat;

打印输出如下,先调用派生类析构函数,再调用基类析构函数:

Cat release
Animal release

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐