第七十九天学习记录:C++基础:关键字

关键字

作用:关键字是C++中预先保留的单词(标识符)
在定义变量或者常量的时候,不要用关键字

C++关键字如下:

asm do if return typedef
auto double inline short typeid
bool dynamic_cast int signed typename
break else long sizeof union
case enum mutable static unsigned
catch explicit namespace staric_cast using
char export new struct virtual
class extern operator switch void
const false private template volatile
const_cast float protected this wchar_t
continue for public throw while
default frirend register true
delete goto reinterpret_cast try

标识符命名规则

作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则
1、标识符不能是关键字
2、标识符只能由字母、数字、下划线组成
3、第一个字符必须为字母或下划线
4、标识符中字母区分大小写

部分关键字说明:

C++ 关键字:asm

C++ 关键字 “asm” 用于嵌入汇编语言代码。通过使用 “asm” 关键字,可以在 C++ 程序中直接插入汇编指令,以便实现对底层硬件的访问或执行特定的机器级操作。然而,需要注意的是,使用 “asm” 关键字会使代码与特定的平台或编译器紧密耦合,因此需要谨慎使用,并且可能不具有可移植性。在现代的 C++ 标准中,推荐使用更高级的语言特性和标准库来提供所需的功能,而避免直接使用汇编代码,除非绝对必要。

C++ 关键字:inline

C++ 关键字 “inline” 用于向编译器提供函数内联的建议。当函数被声明为 “inline” 时,编译器可以选择性地对该函数进行内联展开,将函数的代码插入到调用处,而不是通过常规的函数调用机制进行调用。这样可以提高程序的执行效率,减少函数调用的开销。
使用 “inline” 关键字并不能保证函数一定会被内联展开,它只是向编译器发出的一种建议。最终是否进行内联展开还取决于编译器的判断和优化策略。通常情况下,较小的、频繁调用的函数更有可能被内联展开。
需要注意的是,在头文件中定义的函数如果声明为 “inline”,则每个包含该头文件的源文件都会生成该函数的副本,可能会导致代码膨胀和链接错误。为了避免这种情况,通常将函数的定义与声明分离,只在声明处加上 “inline” 关键字。
总之,使用 “inline” 关键字可以提高函数调用的效率,但需要谨慎使用,以避免潜在的问题和副作用。

C++ 关键字:mutable

C++ 关键字 “mutable” 用于修饰类中的成员变量。当成员变量被声明为 “mutable” 时,即使在 const 成员函数中,该成员变量仍然可以修改。
普通情况下,const 成员函数是不允许修改类的非静态成员变量的,因为 const 成员函数被视为不会对对象状态进行更改的函数。但有时候可能会遇到一些特殊情况,需要在 const 成员函数中修改某个成员变量的值,这时可以使用 “mutable” 关键字来实现此目的。
以下是使用 “mutable” 关键字的示例代码:

class Example {
    
    
private:
    mutable int count; // mutable 成员变量

public:
    void increment() const {
    
    
        ++count; // 在 const 成员函数中修改 mutable 成员变量的值
    }
};

在上述示例中,count 被声明为 mutable,所以即使在 const 成员函数 “increment” 中,也可以对 count 进行自增操作。
需要注意的是,尽管 mutable 成员变量可以在 const 成员函数中修改,但这并不意味着 const 成员函数可以修改对象的其他部分。const 成员函数仍然要遵守不修改对象状态的原则,只能修改被声明为 mutable 的成员变量。
总结来说,关键字 “mutable” 允许在 const 成员函数中修改被标记为 mutable 的成员变量,提供了一种特殊的例外情况。

C++ 关键字:catch

C++ 关键字 “catch” 用于处理异常情况。在使用异常处理机制时,可以使用 “try-catch” 块来捕获和处理可能抛出的异常。
以下是使用 “catch” 关键字的基本语法:

try {
    
    
    // 可能会抛出异常的代码
} 
catch (ExceptionType1 e1) {
    
    
    // 处理 ExceptionType1 类型的异常
} 
catch (ExceptionType2 e2) {
    
    
    // 处理 ExceptionType2 类型的异常
}
// ...
catch (...) {
    
    
    // 处理其他类型的异常
}

在上述代码中,异常处理过程包含在 “try” 块内,其中可能会抛出异常的代码写在该块内部。如果在执行 “try” 块内的代码时发生了异常,那么程序会跳转到适当的 “catch” 块进行异常处理。
每个 “catch” 块都会指定一个异常类型作为参数,当发生相应类型的异常时,对应的 “catch” 块中的代码会被执行。可以有多个 “catch” 块来处理不同类型的异常,根据异常类型的匹配性,会选择最匹配的 “catch” 块进行处理。可以按照需要添加任意数量的 “catch” 块。
最后的 “catch (…) {}” 是一个特殊的 catch 块,它可以用来捕获所有未被前面的 catch 块捕获的异常。这种形式的 catch 块被称为省略号(ellipsis)或通配符(wildcard)捕获,可以用于处理未知的异常类型或作为默认情况的处理方式。
在 “catch” 块中,可以编写特定异常类型发生时的处理代码,例如记录日志、输出错误信息等。还可以选择继续抛出异常(使用 “throw” 关键字)或执行其他逻辑来进行异常处理。
总结来说,关键字 “catch” 用于捕获和处理可能抛出的异常,可以通过多个 “catch” 块来处理不同类型的异常,并可以使用省略号形式的 catch 块来处理未知的异常类型。

C++关键字:explicit

在 C++ 中,关键字 “explicit” 用于修饰类的构造函数,表明该构造函数是显式的,即禁止隐式转换。
通常情况下,C++ 允许使用构造函数进行隐式转换。例如,当一个参数类型与构造函数的参数类型不完全匹配但可以进行隐式转换时,编译器会自动调用该构造函数来创建对象。然而,有时候我们希望禁止这种隐式转换的行为,只能通过显式调用构造函数来创建对象。这时就可以使用 “explicit” 关键字。
以下是使用 “explicit” 关键字的示例:

class Example {
    
    
public:
    explicit Example(int value) {
    
    
        // 构造函数实现
    }
};

void function(Example obj) {
    
    
    // 函数实现
}

int main() {
    
    
    Example obj1(10);      // 直接调用构造函数创建对象
    Example obj2 = 20;     // 错误,禁止隐式转换
    Example obj3 = Example(30);  // 正确,显式调用构造函数来创建对象

    function(obj1);       // 正确,调用函数并传递对象
    function(40);         // 错误,禁止隐式转换
    function(Example(50));  // 正确,显式调用构造函数来创建对象并传递给函数

    return 0;
}

在上述示例中,类 “Example” 的构造函数被声明为显式的,并使用了 “explicit” 关键字。这意味着禁止对构造函数进行隐式调用和隐式转换。只能通过显式调用构造函数来创建对象。
使用 “explicit” 关键字可以有效地防止不必要的类型转换和错误的语义,提高代码的可读性和安全性。
总结来说,关键字 “explicit” 用于修饰类的构造函数,表示禁止隐式转换,只允许显式调用构造函数来创建对象。

C++关键字:namespace

在C++中,关键字namespace用于定义命名空间。命名空间提供了一种将全局作用域划分为多个不同的区域以组织代码的机制。
通过使用命名空间,我们可以避免不同的标识符之间的冲突。当我们将相关的变量、函数和类型放置在一个命名空间中时,它们的名称就会被限定在该命名空间内部。
以下是定义命名空间及其使用的示例:

namespace MyNamespace {
    
    
    int x;
    
    void myFunction() {
    
    
        // 函数实现
    }
}

int main() {
    
    
    MyNamespace::x = 10;         // 访问命名空间中的变量
    MyNamespace::myFunction();   // 调用命名空间中的函数

    return 0;
}

在上述示例中,我们首先通过namespace关键字定义了一个命名空间MyNamespace。然后,在命名空间中定义了一个变量x和一个函数myFunction。
在main函数中,要访问命名空间中的变量或函数,我们需要在被访问的标识符前加上命名空间的名称,并使用双冒号(::)来表示作用域解析运算符。这样就可以访问和调用命名空间中的成员。
使用命名空间有助于组织代码、避免名称冲突,并提高代码的可读性和可维护性。
需要注意的是,命名空间可以嵌套定义,可以在全局作用域、其他命名空间中定义命名空间。也可以使用using关键字来引入特定的命名空间或命名空间中的成员,以节省书写命名空间名称的时间和代码量。
总结:namespace是C++关键字,用于定义命名空间,通过命名空间可以将代码进行有组织的划分,避免名称冲突,提高代码可读性和可维护性。

C++关键字:using

在C++中,using是一个关键字,用于引入命名空间或命名空间中的特定成员,以便在代码中可以直接使用它们,而无需使用完全限定的名称。
using关键字有两种主要用法:
引入整个命名空间:

using namespace MyNamespace;

这样,在当前作用域中就可以直接使用MyNamespace命名空间中的所有成员,无需使用命名空间前缀。这种用法可以简化代码,但要注意避免命名冲突。
引入单个成员:

using MyNamespace::myFunction;

这样,在当前作用域中就可以直接使用MyNamespace命名空间中的myFunction函数,无需使用命名空间前缀。这种用法只引入了指定的成员,并不会引入命名空间中的其他成员。
使用using关键字可以使代码更加简洁,尤其在频繁使用某个命名空间中的成员时。然而,在较大的代码库中,过多的using语句可能导致命名冲突和可读性下降,因此需要谨慎使用。
需要注意的是,为了避免潜在的命名冲突,推荐将using语句放在尽可能小的作用域中,并避免在头文件中使用using语句。
总结:using是C++关键字,用于引入命名空间或命名空间中的特定成员,以便在代码中可以直接使用它们。可通过引入整个命名空间或单个成员来简化代码书写。需要注意避免命名冲突,并谨慎选择使用时的范围和位置。

C++关键字:export

在C++中,export曾经是一个关键字,用于指示模板代码的显式实例化和导出。该关键字允许将模板定义和声明分离,并将显式实例化的模板代码放在单独的源文件中。
然而,需要注意的是,自从C++17起,export关键字的使用已被移除,被废弃并不再使用。这意味着在现代的C++标准中(包括C++17、C++20等),不再需要或不能使用export关键字。
因此,在当前版本的C++中,如果您遇到关键字export,它通常会被视为普通的标识符而非关键字。
总结:在现代的C++标准中,如C++17和C++20,已废弃并移除了export关键字。因此,在当前版本的C++中,不再需要或不能使用export关键字。

C++关键字:operator

C++中的关键字"operator"用于定义和重载运算符。通过使用"operator"关键字,可以对类的对象进行特定的运算符行为定义和修改。例如,可以使用"operator+"来定义两个类对象相加的操作,使用"operator="来定义对象之间的赋值操作。
需要注意的是,"operator"关键字必须与具体的运算符一起使用,以指定要定义或重载的运算符。例如,"operator+"表示重载加法运算符。
以下是常见的重载运算符及其对应的"operator"关键字:
加法运算符:operator+
减法运算符:operator-
乘法运算符:operator*
除法运算符:operator/
赋值运算符:operator=
索引访问运算符(下标运算符):operator[]
函数调用运算符:operator()
相等比较运算符:operator==
不等比较运算符:operator!=
大于比较运算符:operator>
小于比较运算符:operator<
自增运算符:operator++
自减运算符:operator–
请注意,在重载运算符时应谨慎使用,确保符合预期的语义和行为,并遵循良好的编程实践。

C++关键字:template

C++中的关键字"template"用于泛型编程,它允许编写通用的代码模板,能够在不同的数据类型上进行重复使用。
通过使用"template"关键字,可以定义函数模板和类模板。函数模板允许在调用时以不同的数据类型作为参数,生成相应的函数实例。类模板则可以定义通用的类结构,其中的成员函数和成员变量可以适用于多种不同的数据类型。
以下是使用"template"关键字定义函数模板和类模板的示例:
1、函数模板:

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

int main() {
    
    
    int result1 = add(3, 4); // 调用add<int>(3, 4),返回7
    double result2 = add(2.5, 1.6); // 调用add<double>(2.5, 1.6),返回4.1
}

2、类模板:

template <typename T>
class Stack {
    
    
private:
    std::vector<T> elements;
public:
    void push(T value) {
    
    
        elements.push_back(value);
    }

    T pop() {
    
    
        if (!elements.empty()) {
    
    
            T value = elements.back();
            elements.pop_back();
            return value;
        }
        throw std::out_of_range("Stack is empty");
    }
};

int main() {
    
    
    Stack<int> intStack; // 创建一个存储int类型的栈对象
    intStack.push(2);
    intStack.push(5);
    intStack.pop(); // 返回5

    Stack<double> doubleStack; // 创建一个存储double类型的栈对象
    doubleStack.push(1.2);
    doubleStack.push(3.4);
    doubleStack.pop(); // 返回3.4
}

通过使用"template"关键字,我们可以编写通用且灵活的代码,在不同的数据类型上进行重复利用,提高了代码的复用性和可扩展性。

C++关键字:wchar_t

C++中的关键字"wchar_t"用于表示宽字符类型。它是一种用于存储和处理宽字符数据的数据类型。
"wchar_t"数据类型可以用于表示更广范围的字符,包括ASCII字符集以外的字符,如Unicode字符。通常情况下,一个"wchar_t"变量可以存储一个宽字符,其大小在不同的编译器实现中可能会有所不同。
使用"wchar_t"类型时,可以配合一些宽字符处理函数和库来进行宽字符的输入、输出和处理操作。例如,可以使用"wcin"和"wcout"来进行宽字符的标准输入和输出。
以下是使用"wchar_t"的简单示例:

#include <iostream>

int main() {
    
    
    wchar_t wideChar = L'宽'; // 使用L前缀表示宽字符常量

    std::wcout << wideChar << std::endl; // 输出宽字符到标准输出

    return 0;
}

需要注意的是,宽字符类型"wchar_t"在不同的平台和编译器之间可能存在差异。为了确保代码的可移植性,可以使用头文件中的"type_traits"来判断"wchar_t"的具体大小(例如使用std::is_same<wchar_t, int>::value)或使用头文件中提供的宽字符处理函数和类型定义来进行宽字符操作。

C++关键字:throw

"throw"是C++中的关键字,用于抛出异常。当程序遇到错误或异常情况时,可以使用throw关键字来主动引发异常并将控制权传递给异常处理机制。
使用throw关键字时,通常会抛出一个异常对象,可以是C++内置类型、自定义类或标准库提供的异常类,用于描述异常的类型和信息。
以下是throw关键字的基本语法示例:

throw exception; // 抛出一个异常对象

catch关键字用于捕获并处理抛出的异常。异常被抛出后,程序会沿着调用栈依次查找匹配的catch块,直到找到能够处理异常的catch语句。
以下是一个简单的异常处理代码示例:

#include <iostream>

void divide(int dividend, int divisor) {
    
    
    if (divisor == 0) {
    
    
        throw std::runtime_error("Divide by zero error"); // 抛出异常对象
    }
    
    int result = dividend / divisor;
    std::cout << "Result: " << result << std::endl;
}

int main() {
    
    
    try {
    
    
        divide(10, 2); // 没有抛出异常
        divide(20, 0); // 抛出异常
        divide(30, 5); // 未执行,因为前一次调用中抛出了异常
    } catch(const std::runtime_error& e) {
    
     // 捕获异常并进行处理
        std::cout << "Exception caught: " << e.what() << std::endl;
    }
    
    return 0;
}

在上述示例中,divide函数中当除数为0时,抛出了一个std::runtime_error类型的异常对象。在主函数的try块中调用divide函数,并使用catch语句捕获并处理可能抛出的异常。
需要注意的是,为了能够捕获特定类型的异常,catch语句的参数应该与抛出的异常类型匹配或兼容。同时,在程序中适当地使用try-catch块可以增强程序的健壮性和错误处理能力。

C++关键字:frirend

“friend” 是 C++ 的关键字,用于声明友元关系。友元关系可以使一个函数或类访问另一个类的私有成员。
在 C++ 中,一般情况下,只有本类的成员函数才能直接访问该类的私有成员。但通过使用 “friend” 关键字,可以将其他函数、类或者整个类声明为友元,从而使其能够访问当前类的私有成员。
以下是 friend 关键字的基本语法示例:

class MyClass {
    
    
private:
    int privateData;

public:
    friend void friendFunction(); // 声明友元函数

    friend class FriendClass; // 声明友元类

    // ...
};

void friendFunction() {
    
    
    MyClass obj;
    obj.privateData = 10; // 可以访问 privateData
}

class FriendClass {
    
    
public:
    void accessPrivateData(MyClass& obj) {
    
    
        obj.privateData = 20; // 可以访问 privateData
    }
};

在上述示例中,friendFunction() 被声明为 MyClass 的友元函数,因此可以在函数内部访问 MyClass 的私有成员 privateData。同样地,FriendClass 被声明为 MyClass 的友元类,因此可以通过其成员函数 accessPrivateData() 访问 MyClass 的私有成员。
需要注意的是,友元关系破坏了封装性,增加了程序的复杂性和耦合度,因此应谨慎使用。仅当特定的函数或类需要访问类的私有成员,并且没有其他更合适的设计方案时,才考虑使用友元关系。

C++关键字:dynamic_cast

“dynamic_cast” 是 C++ 的关键字,用于在继承层次结构中进行动态类型转换。它用来确保在运行时进行安全的类型转换,并检查转换的有效性。
dynamic_cast 主要用于以下情况:
1、将指向基类的指针或引用转换为指向派生类的指针或引用。
2、在没有多态性的情况下,在类之间进行安全的向下转型。
以下是 dynamic_cast 关键字的基本语法示例:

class Base {
    
    
    // 基类定义...
};

class Derived : public Base {
    
    
    // 派生类定义...
};

Base* basePtr = new Derived; // 指向派生类对象的基类指针

Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // 安全地将基类指针转换为派生类指针

在上述示例中,basePtr 是一个指向派生类 Derived 对象的基类指针。通过使用 dynamic_cast,可以将 basePtr 安全地转换为 Derived* 类型的派生类指针 derivedPtr。如果转换成功,则 derivedPtr 指向同一个派生类对象;如果转换失败(即 basePtr 实际指向的对象不是 Derived 类型),则 dynamic_cast 返回一个空指针。
需要注意的是,dynamic_cast 只能用于具有多态性(即存在虚函数)的类之间的转换。另外,如果将一个指针或引用转换为无关类的指针或引用,或者转换不可行时,dynamic_cast 将返回空指针(对于指针类型)或抛出 std::bad_cast 异常(对于引用类型)。
因为 dynamic_cast 需要在运行时进行类型检查,所以它的效率比较低。在使用 dynamic_cast 时,需要谨慎考虑设计和使用继承关系,避免频繁的类型转换操作。

C++关键字:staric_cast

“static_cast” 是 C++ 的关键字,用于进行静态类型转换。它可以在编译时进行类型转换,但不进行运行时的类型检查。
static_cast 可以用于以下场景:
1、用于非多态类型的转换,如基本数据类型之间的转换。
2、用于类层次结构中的向上转型(派生类指针或引用到基类指针或引用)。
3、用于具有多态性的类层次结构中,将基类指针或引用转换为派生类指针或引用。然而,在该情况下,如果不能保证转换的安全性,最好使用 dynamic_cast 进行动态类型转换。
以下是 static_cast 关键字的基本语法示例:

class Base {
    
    
    // 基类定义...
};

class Derived : public Base {
    
    
    // 派生类定义...
};

int intValue = 10;
double doubleValue = static_cast<double>(intValue); // 将 int 转换为 double

Derived derivedObj;
Base* basePtr = static_cast<Base*>(&derivedObj); // 将派生类指针转换为基类指针

Base* basePtr2 = new Base;
Derived* derivedPtr = static_cast<Derived*>(basePtr2); // 非安全的基类指针转换为派生类指针

在上述示例中,首先使用 static_cast 将一个整数变量 intValue 转换为 double 类型的变量 doubleValue。然后,将派生类对象的指针 derivedObj 静态转换为基类指针 basePtr。最后,尝试将一个基类指针 basePtr2 转换为派生类指针 derivedPtr,这是一种非安全的类型转换。
需要注意的是,static_cast 不提供运行时的类型检查,因此在进行类型转换时应谨慎。如果对于多态类型的转换,无法确保转换的安全性,建议使用 dynamic_cast 进行动态类型转换。

C++关键字:reinterpret_cast

“reinterpret_cast” 是 C++ 的关键字之一,用于进行底层的类型转换。它可以将一个指针或引用从一种类型转换为另一种不相关的类型。
reinterpret_cast 可以用于以下场景:
在不同类型之间进行指针或引用的强制转换。
进行不同类型之间的指针或引用的底层二进制位的重新解释。
下面是 reinterpret_cast 关键字的基本语法示例:

int intValue = 10;
char charValue = reinterpret_cast<char>(intValue); // 将 int 转换为 char

int* intPointer = new int(42);
float* floatPointer = reinterpret_cast<float*>(intPointer); // 将 int 指针转换为 float 指针

struct MyStruct {
    
    
    int x;
    double y;
};

int* intArray = new int[5];
MyStruct* structPtr = reinterpret_cast<MyStruct*>(intArray); // 将 int 数组指针转换为自定义结构体指针

在上述示例中,首先使用 reinterpret_cast 将整数变量 intValue 转换为字符变量 charValue。然后,将整数指针 intPointer 转换为浮点数指针 floatPointer,进行底层的指针解释。最后,尝试将 int 数组指针 intArray 转换为自定义结构体指针 structPtr,进行底层的指针解释。
需要注意的是,reinterpret_cast 进行的类型转换没有任何类型检查和安全保证。因此,在使用 reinterpret_cast 进行类型转换时必须非常小心,确保转换的结果是可靠且安全的。通常情况下,应优先考虑使用其他更安全的类型转换操作符(如 static_cast 或 dynamic_cast)。

猜你喜欢

转载自blog.csdn.net/weixin_45694614/article/details/131268458