c++基础补强-Day04

namespace 极简总结

  1. 命名空间作用 :划分独立作用域,解决同名变量 / 函数冲突,模块化管理代码;用::访问空间内成员。

  2. 两种 using 用法

    • using 命名空间::名字(using 声明):仅引入单个符号,冲突少,工程推荐;

    • using namespace 命名空间(using 指令):引入全部符号,简写方便但易重名,仅小型程序用。

  3. 嵌套命名空间 :空间内再套空间,层级管理;C++17 可简写A::B,多层::访问。

  4. 匿名命名空间:无名称,内部内容仅当前文件可见,替代 static 做文件私有函数 / 变量。

  5. 命名空间别名namespace 别名 = 原空间,简化超长嵌套命名空间书写。

  1. 定义命名空间

语法:

cpp

运行

复制代码
namespace 空间名 {
    // 变量、函数、类、结构体
    int a = 10;
    void func() {}
}

二、访问命名空间元素:using 声明 /using 指令

  1. 限定符直接访问(基础写法)

不使用任何 using,每次写全空间名:

cpp

运行

复制代码
std::cout << LibA::a << endl;
LibA::func();
  1. using 声明(using 标识符)

语法:using 空间::名字; 作用:只引入单个指定符号,仅该名字可直接使用,其他符号仍需加空间前缀。

cpp

运行

复制代码
#include <iostream>
using std::cout; // 只引入std里的cout

int main() {
    cout << "直接用cout" << endl;
    // cin 未声明,必须写 std::cin
    std::cin >> x;
    return 0;
}
  1. using 指令(using namespace 空间)

语法:using namespace 空间名; 作用:一次性引入整个空间所有符号,空间内所有名称都可无前缀使用。

cpp

运行

复制代码
#include <iostream>
using namespace std; // 导入std全部内容

int main() {
    cout << "hello";
    cin >> x;
    endl;
    return 0;
}

三、嵌套命名空间

  1. 概念

命名空间内部再定义 namespace,形成层级结构,适合多层级代码分组(如项目→模块→工具)。

  1. 定义方式

老式写法(C++17 前)

cpp

运行

复制代码
namespace Project {
    namespace Net {
        void send() {
            cout << "网络发送" << endl;
        }
    }
}

C++17 简化语法(推荐)

cpp

运行

复制代码
namespace Project::Net {
    void send() {}
}
  1. 使用嵌套命名空间

多层::逐层访问:

cpp

运行

复制代码
// 完整写法
Project::Net::send();

// 搭配using简化
using namespace Project::Net;
send();

四、匿名命名空间 + 命名空间别名

  1. 匿名命名空间(无名字 namespace)

定义

cpp

运行

复制代码
namespace {
    int temp = 100;
    void helper() {}
}

核心特性 & 作用

  1. 作用域仅限当前文件 :等价于加 static,其他 cpp 文件无法访问里面的内容;

  2. 替代全局 static 变量 / 函数,C++ 推荐优先用匿名空间;

  3. 使用场景:只在当前源文件内部使用的工具函数、临时变量,防止跨文件命名冲突。

使用

匿名空间内的符号直接使用,无需前缀:

cpp

运行

复制代码
helper();
cout << temp;
  1. 命名空间别名(给长空间简写)

语法:namespace 别名 = 原空间名; 解决多层嵌套、超长命名空间书写繁琐问题。

cpp

运行

复制代码
// 超长嵌套空间
namespace Game::Logic::Battle::Skill {
    void fire() {}
}

// 设置别名
namespace Skill = Game::Logic::Battle::Skill;

// 使用别名调用
Skill::fire();

也可给普通空间起别名:

cpp

运行

复制代码
namespace A = LibA;
A::print();

二、nullptr(C++11 空指针)

  1. nullptr 关键字,类型 std::nullptr_t,专门代表空指针

  2. 对比 NULL / 0

  • NULL 是宏 #define NULL 0,本质整型;0 是字面量 int

  • 重载场景下 NULL/0 会匹配 int 版本,产生歧义;nullptr 只会匹配指针

  1. 转换规则
  • nullptr 可隐式转为任意指针类型

  • 普通指针不能隐式转 nullptr_t

  1. 规范:C++11 后统一用 nullptr,不用 NULL、0 表示空指针

class & struct 完整知识点梳理

一、基础核心区别

  1. 本质相同 classstruct 都属于自定义复合类型,都能写:成员变量、成员函数、构造、析构、重载、继承、多态等,语法几乎互通。

  2. 两大默认差异(考点核心)

1)默认成员访问权限

  • struct:所有成员默认 public

  • class:所有成员默认 private 示例:

cpp

运行

复制代码
struct S {
    int a; // public
};
class C {
    int a; // private
};

2)默认继承方式

cpp

运行

复制代码
// struct 默认 public 继承
struct Son : Base {};

// class 默认 private 继承
class Son : Base {};

二、三种访问权限 public /protected/private

  1. public 公有 外部任意代码、子类、自身都能直接访问。

  2. protected 保护 仅自身 + 派生类可以访问,外部不能访问。

  3. private 私有 只有类内部自身能访问,子类、外部均不可访问。

手动修改权限:用访问控制块分段声明

cpp

运行

复制代码
class Test {
private:
    int x;
protected:
    int y;
public:
    void func(){}
};

四、函数重载(静态多态)

  1. 定义:同一作用域,同名函数,参数列表不同(个数 / 类型 / 顺序)

  2. 不能作为重载区分:仅返回值不同、仅参数名不同

  3. 重载解析:编译器自动匹配实参,优先级:精确匹配 > 提升转换 > 普通转换;多重等价匹配会报歧义

  4. 重载 vs 函数模板

  • 重载:手动写每个版本,逻辑可不同,类型固定有限

  • 模板:一套代码自动生成多类型,逻辑统一,扩展性强

五、inline 内联函数

  1. inline 只是给编译器的优化建议,非强制命令

  2. 作用:调用处展开函数体,消除函数调用压栈跳转开销

  3. 使用规范

  • 短小函数(1~5 行、无循环 / 递归)放头文件,加 inline,解决多文件 include 重复定义报错

  • 复杂函数(循环、递归、代码量大)放 cpp,不用 inline,编译器会直接忽略 inline

  1. 验证方式:编译加 - O2 优化,查看汇编,无 call 指令代表成功内联

  2. 类内直接定义的成员函数,默认隐式 inline

六、const 全场景

  1. const 普通变量

初始化后不可修改,定义时必须赋值;有类型、作用域,优于 #define 宏

  1. const 指针(必考区分)

  2. const int* p 指向常量指针:内容不可改,指针可换指向

  3. int* const p 指针常量:指针地址固定,内容可修改

  4. const int* const p 双重 const:内容、指针均不可改

  5. const 修饰函数参数

const T& 只读引用,函数内禁止修改外部数据,避免拷贝,提升安全

  1. const 修饰返回值

返回const T* / const T&,外部无法通过返回值修改内部数据;内置类型加 const 无意义

  1. const 成员函数

函数末尾加 const,承诺不修改类成员;mutable 修饰变量例外,const 函数内仍可修改 规则:const 对象只能调用 const 成员函数