cpp中的namespace详解
namespace的作用主要是为了避免名字冲突和组织代码。
命名空间在C++中是一个非常重要的特性,它帮助开发者更好地管理代码和避免潜在的冲突。
具体来说,它有以下几个主要用途
- 避免名字冲突
在大型项目中可能会有很多个类、函数或变量使用相同的名称。使用命名空间可以将这些名称分组,从而避免冲突。
#include <iostream>namespace ProjectA {void display() {std::cout << "Project A Function" << std::endl;}
}namespace ProjectB {void display() {std::cout << "Project B Function" << std::endl;}
}int main() {ProjectA::display(); // 调用Project A的函数ProjectB::display(); // 调用Project B的函数return 0;
}
- 代码组织
命名空间有助于逻辑上组织代码,使代码结构更加清晰。可以帮助开发者将相关的功能组织在一起,便于管理和维护。
#include <iostream>namespace Math {void add(int a, int b) {std::cout << "Sum: " << (a + b) << std::endl;}void subtract(int a, int b) {std::cout << "Difference: " << (a - b) << std::endl;}
}namespace Utils {void printGreeting() {std::cout << "Welcome to the Math Program!" << std::endl;}void printFarewell() {std::cout << "Thank you for using the Math Program!" << std::endl;}
}
int main() {Utils::printGreeting();Math::add(5, 3);Math::subtract(5, 3);Utils::printFarewell();return 0;
}
- 提供作用域
命名空间为其中定义的标识符提供了一个独立的作用域。即使在同一个文件中,可以定义多个同名的函数或变量,只要它们位于不同的命名空间中。
#include <iostream>namespace Math {int value = 10; // Math命名空间内的变量void display() {std::cout << "Math Value: " << value << std::endl;}
}namespace Science {int value = 20; // Science命名空间内的变量void display() {std::cout << "Science Value: " << value << std::endl;}
}int main() {Math::display(); // 调用Math命名空间的display函数Science::display(); // 调用Science命名空间的display函数// 可以使用不同命名空间的变量std::cout << "Accessing Math value: " << Math::value << std::endl;std::cout << "Accessing Science value: " << Science::value << std::endl;return 0;
}
- 嵌套命名空间
C++支持嵌套命名空间,可以进一步组织代码,避免名称冲突。
#include <iostream>namespace Outer {namespace Inner {void display() {std::cout << "Hello from Inner Namespace!" << std::endl;}int value = 42;}void show() {std::cout << "Hello from Outer Namespace!" << std::endl;}
}int main() {Outer::show(); // 调用外部命名空间的函数Outer::Inner::display(); // 调用嵌套命名空间的函数std::cout << "Inner value: " << Outer::Inner::value << std::endl; // 访问嵌套命名空间的变量return 0;
}
- 使用简化
可以使用using声明来简化命名空间内标识符的访问。
#include <iostream>namespace Math {int add(int a, int b) {return a + b; // 加法函数}int subtract(int a, int b) {return a - b; // 减法函数}
}using namespace Math; // 使用整个 Math 命名空间int main() {int sum = add(5, 3); // 直接调用函数,无需前缀int difference = subtract(5, 3); // 直接调用函数std::cout << "Sum: " << sum << std::endl; // 输出结果std::cout << "Difference: " << difference << std::endl; // 输出结果return 0;
}
在不同的cpp文件中使用相同的 namespace xxx;
分析:
1、共享命名空间:所有文件都使用命名空间 xxx,避免命名冲突,同时保持代码的整洁。
2、功能分离:日志记录和实用工具功能分开,易于管理和扩展。
3、模块化设计:可以独立编译和链接各个文件,增强了代码的可维护性。
4、一致性:通过相同的命名空间,开发者可以清楚地识别出相关功能。C++会将它们合并。
logger/Logger (h/cpp)
#ifndef LOGGER_H
#define LOGGER_H#include <string>namespace xxx {class Logger {public:void log(const std::string& message);};
}#endif====================================================#include "Logger.h"
#include <iostream>namespace xxx {void Logger::log(const std::string& message) {std::cout << "Log: " << message << std::endl;}
}
utilities/Utils (h/cpp)
#ifndef UTILS_H
#define UTILS_Hnamespace xxx {class Utils {public:static void printHello();};
}#endif====================================================#include "Utils.h"
#include <iostream>namespace xxx {void Utils::printHello() {std::cout << "Hello from Utils!" << std::endl;}
}
main.cpp
#include "logger/Logger.h"
#include "utilities/Utils.h"int main() {xxx::Logger logger;logger.log("This is a log message.");xxx::Utils::printHello();return 0;
}
拓展
使用相同的 namespace xxx时函数名和参数都相同会出现什么情况呢?
如果在两个不同的c++文件中使用相同的命名空间xxx,并且里面的函数名相同,编译时会出现重定义错误,这是因为统一命名空间内不允许有重复定义的标识符。
使用相同的 namespace xxx时函数名相同和参数类型不相同会出现什么情况呢?
如果参数不同,这种情况称为函数重载。c++允许在同一命名空间中重载函数。及时它们的名称相同,只要是参数列表不同(包括参数数量或类型)
如果不使用namespace会出现什么情况呢?
file1.cpp
#if 0 //未使用namespace
#include <iostream>int setting = 42; // 全局变量void printSetting() {std::cout << "file1 setting: " << setting << std::endl;
}void display() {std::cout << "Display from file1" << std::endl;
}
#else //使用namespace
namespace file1 {int setting = 42;void printSetting() {std::cout << "file1 setting: " << setting << std::endl;}
}
namespace FileA {void display() {std::cout << "Display from fileA" << std::endl;}
}
#endif
file2.cpp
#include <iostream>
#if 0 //未使用namespace
int setting = 100; // 同名全局变量,覆盖了 file1.cpp 中的 settingvoid printUserSetting() {std::cout << "file2 setting: " << setting << std::endl;
}void display() {std::cout << "Display from fileB" << std::endl;
}
#else //使用namespace
namespace file2 {int setting = 100;void printUserSetting() {std::cout << "file2 setting: " << setting << std::endl;}
}
namespace fileB {void display() {std::cout << "Display from fileB" << std::endl;}
}
#endif
main.cpp
#include <iostream>
#if 0 //未使用namespace
void display(); // 声明void printSetting(); // 声明void printUserSetting(); // 声明
#else //使用namespace
namespace file1 {void printSetting();
}namespace file2 {void printUserSetting();
}namespace fileA {void display();
}namespace fileB {void display();
}
#endifint main() {
#if 0 //未使用namespaceprintSetting(); // 期望输出 file1 setting: 42printUserSetting(); // 期望输出 file2 setting: 100display(); // 编译时错误:不确定调用哪个cpp下的display函数
#else //使用namespacefile1::printSetting(); // 输出 file1 setting: 42file2::printUserSetting(); // 输出 file2 setting: 100fileA::display(); // 调用 fileA 命名空间中的函数fileB::display(); // 调用 fileB 命名空间中的函数
#endifreturn 0;
}
1、命名冲突:不同文件或库中相同名称的类、函数或变量可能导致编译错误,提示重定义。因为编译器无法区分它们。
2、可读性降低:代码的结构可能变得混乱,特别是在大型项目中,所有的标识符(如函数名、变量名等)都在一个全局范围内,难以追踪各个功能的来源。增加了理解和维护的难度。
3、维护困难:在修改或扩展代码时,可能会意外影响其他部分,因为没有清晰的分隔。随着项目扩展,维护人员可能会对 display 函数的来源感到困惑,增加了调试和代码理解的难度。
4、全局作用域污染:所有定义都在全局作用域中,增加了命名冲突的风险,尤其是在与第三方库交互时。虽然 printSetting 和 printUserSetting 函数存在,但是由于同名全局变量的定义,可能导致意外的行为。例如,可能会误用 setting 变量,造成混淆和难以追踪的错误。
根据上面的案例及总结。我们可以了解到为什么要使用命名空间。
使用命名空间可以有效地解决这些问题,提升代码的组织性和可维护性。
记录的同时,欢迎大家一起补充学习!
相关文章:
cpp中的namespace详解
namespace的作用主要是为了避免名字冲突和组织代码。 命名空间在C中是一个非常重要的特性,它帮助开发者更好地管理代码和避免潜在的冲突。 具体来说,它有以下几个主要用途 避免名字冲突 在大型项目中可能会有很多个类、函数或变量使用相同的名称。使用…...
request库的使用 | get请求
requests 库的 get 方法用于发送 HTTP GET 请求。GET 请求通常用于请求服务器发送数据。 1、导入 requests 库: import requests 2、发送 GET 请求: 使用 requests.get() 方法发送请求。 response requests.get(urlhttp://www.jd.com) 3、查看响应…...
理想低通信道和理想带通信道的区别
一、定义与特性 理想低通信道(可通过<MAX): 定义:理想低通信道允许信号的所有低频分量,只要其频率不超过某个上限值,都能够不失真地通过此信道。而频率超过该上限值的所有高频分量都不能通过该信道。特…...
LAMP架构搭建
目录 LAMP架构搭建 编译安装Apache httpd服务 1、需要的安装包 2、关闭防火墙和核心防护 3、安装环境依赖包 4、配置软件模块 5、编译及安装 6、优化配置文件路径(可不做) 7、添加httpd系统服务 8、修改httpd 服务配置文件 9、浏览器访问验证…...
RT-DETR
SSE represents the single-scale Transformer encoder,CSF represents cross-scale fusion. AIFI and CCFF are the two modules designed into 作者的 hybrid encoder 截止到发文时间的issue数,多吓人呐,不建议复现...
【算法——KMP】
1理解next数组定义:最长相等前后缀(不含当前字符并且不能是整体) 算法讲解100【扩展】 KMP算法原理和代码详解_哔哩哔哩_bilibili next数组的值:假设这个i出现了不匹配就从next[i]的位置开始在再匹配 2next数组生成 看一下是怎…...
视频监控相关笔记
一、QT 之 QTreeWidget 树形控件 Qt编程指南,Qt新手教程,Qt Programming Guide 一个树形结构的节点中的图表文本 、附带数据的添加: QTreeWidgetItem* TourTreeWnd::InsertNode(NetNodeInfo node, QTreeWidgetItem* parent_item) { // …...
React 中,构建组件的方式
1. 函数组件(Function Components) 函数组件是最简单的组件形式,通常用于展示性的组件,不涉及复杂的生命周期方法。 import React from react;function Welcome(props) {return <h1>Hello, {props.name}</h1>; }exp…...
Android开发高频面试题之——Android篇
Android开发高频面试题之——Android篇 Android开发高频面试题之——Java基础篇 Android开发高频面试题之——Kotlin基础篇 Android开发高频面试题之——Android基础篇 1. Activity启动模式 standard 标准模式,每次都是新建Activity实例。singleTop 栈顶复用。如果要启动的A…...
禁用拷贝构造函数和赋值构造函数
在C中,禁用拷贝构造函数和拷贝赋值操作符的方式通常是为了防止类的对象被意外复制,这对于那些管理独占资源或不应被复制的对象尤为重要。 class LatActiveControlState : public LatState { public:LatActiveControlState() : LatState(LatS_ActiveCont…...
OneDrive for Business with Office Online 部署方案
目录 前言 部署准备 需求分析 用户需求 技术需求 环境准备 硬件要求 软件要求 许可计划 OneDrive for Business 部署 前期准备 域名配置 Azure AD 配置 安装与配置 安装 OneDrive 同步客户端 配置 OneDrive 组策略 数据迁移 Office Online 部署 前期准备 安…...
win10 win11 设置文件权限以解决Onedrive不能同步问题
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
Unity DOTS系列之IJobChunk来迭代处理数据
最近DOTS发布了正式的版本, 我们来分享一下System中如何在System中使用IJobChunk来迭代处理World中的数据,方便大家上手学习掌握Unity DOTS开发。 再回顾一次基于ArcheType Chunk内存管理 我们先再次回顾以下基于ArcheType的Chunk内存管理。每一类Entity都是由一些…...
哈希——哈希表
回顾/本期梗概 上期我们学习了哈希——字符串哈希(空降链接),本期我们将学习哈希中的哈希表。 1、哈希表原理 (1)使用数组下标直接标记元素 哈希表(也叫数列表):是一种高效的、通过把…...
简单了解 JVM
目录 ♫什么是JVM ♫JVM的运行流程 ♫JVM运行时数据区 ♪虚拟机栈 ♪本地方法栈 ♪堆 ♪程序计数器 ♪方法区/元数据区 ♫类加载的过程 ♫双亲委派模型 ♫垃圾回收机制 ♫什么是JVM JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。 虚拟机是指通过软件模…...
已经30岁了,想转行从头开始现实吗?什么样的工作算好工作?
我是29岁那年,完成从转行裸辞副业的职业转型。 如果你把职业生涯看成是从现在开始30岁,到你退休那年,中间这么漫长的30年,那么30岁转行完全来得及; 如果你觉得必须在什么年纪,什么时间内必须完成赚到几十…...
快速理解docker(一)docker 简介
在当今快速迭代的软件开发环境中,如何高效地部署、管理和扩展应用程序成为了开发者们面临的重大挑战。Docker,作为一款开源的容器化平台,凭借其轻量级、可移植性和易于部署的特性,迅速成为了解决这些挑战的热门选择。本文将带您走…...
RHCS认证-Linux(RHel9)-Ansible
文章目录 一、ansible 简介二 、ansible部署三、ansible服务端测试四 、ansible 清单inventory五、Ad-hot 点对点模式六、YAML语言模式七、RHCS-Ansible附:安装CentOS-Stream 9系统7.1 ansible 执行过程7.2 安装ansible,ansible-navigator7.2 部署ansibl…...
【Python】Spyder:科学 Python 开发环境
在数据科学和科学计算领域,Python 已经成为了一个不可或缺的工具。为了提高开发效率和改善编程体验,一个功能强大且用户友好的开发环境是必需的。Spyder(Scientific Python Development Environment)正是这样一个为科学计算和数据…...
SpringBootWeb响应
2. 响应 前面我们学习过HTTL协议的交互方式:请求响应模式(有请求就有响应) 那么Controller程序呢,除了接收请求外,还可以进行响应。 2.1 ResponseBody 在我们前面所编写的controller方法中,都已经设置了…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
