C++面向对象程序设计 - 命名空间

news2025/7/18 4:26:40

        命名空间是ANSI C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。

        在C语言中定义了三个层次的作用域,即文件(编译单元)、函数和复合语句。C++又引入了类作用域,类是出现在文件内的。在不同的作用域中可以定义相同名字的变量,互不干扰,系统能够区别它们。

           例如两个不同的头文件中,命名了的类名相同,同时引入进来会报错【[Error] redefinition of 'class Student'】- 这个错误表明类 Student 被重复定义了。示例如下:

1、s1.h头文件代码:

#include <string>
using namespace std;
// 定义Student学生类
class Student{
	private:
		int num;
		string name;
		int age;
	public:
		Student(int num, string name, int age): num(num), name(name), age(age){}
};

2、s2.h头文件代码:

#include <string>
using namespace std;
// 定义Student学员类
class Student{
	private:
		int num;
		string name;
		int age;
		float wage;		//工资
	public:
		Student(int num, string name, int age, float wage): num(num), name(name), age(age), wage(wage){}
};

3、主文件代码:

#include "s1.h"
#include "s2.h"
using namespace std;

int main(){
	return 0;
}

        以上代码在编译的时候就会出现名字冲突,为了解决这个问题,ANSI C++增加了命名空间(namespace)。所谓命名空间,实际上一个由程序设计者命名的内存区域,可以根据需要指定一些有名字的空间域,把一些全局实体分别放到各个命名空间中,从而与其他全局实体分隔开来。

        如下代码:

namespace ns1{
    int a;
    double b;
}

一、命名空间

        在声明一个命名空间时,花括号内不仅可以包括变量,而且还可以包括以下类型:

  • 变量(可以有初始化)
  • 常量
  • 函数(可以是定义或声明)
  • 结构体
  • 模板
  • 命名空间(在一个命名空间中又定义一个命名空间,即嵌套的命名空间)

示例如下:

#include <iostream>
using namespace std;
namespace ns1{
	const double PI = 3.1415926;
	int age = 30;
	double area(){
		return 2 * 20 * PI;
	}
	namespace ns2{
		float wage = 1500.0f;
	}
}

int main(){
	cout <<ns1::PI <<endl;
	cout <<ns1::age <<endl;
	cout <<ns1::area() <<endl;
	cout <<ns1::ns2::wage <<endl;
	return 0;
}

        运行结果如下图:

二、使用命名空间解决同名冲突

        有了以上的基础后,就可以利用命名空间来解决前端Student类的名字冲突问题了。代码如下:

1、s1.h文件

#include <iostream>
#include <string>
using namespace std;

namespace ns1{
	// 定义Student学生类
	class Student{
		private:
			int num;
			string name;
			int age;
		public:
			Student(int num, string name, int age): num(num), name(name), age(age){}
			void print(){
				cout <<"num:" <<num <<", name:" <<name <<", age:" <<age <<endl;
			}
	};
}

2、s2.h文件

#include <iostream>
#include <string>
using namespace std;

namespace ns2{
	// 定义Student学员类
	class Student{
		private:
			int num;
			string name;
			int age;
			float wage;		//工资
		public:
			Student(int num, string name, int age, float wage): num(num), name(name), age(age), wage(wage){}
			void print(){
				cout <<"num:" <<num <<", name:" <<name <<", age:" <<age <<", wage:" <<wage <<endl;
			}
	};
}

3、main主文件

#include "s1.h"
#include "s2.h"
using namespace std;

int main(){
	ns1::Student s1(100, "Tom", 20);
	ns2::Student s2(1001, "John", 30, 1500.0f);
	// 打印结果信息
	s1.print();
	s2.print();
	return 0;
}

        运行结果如下图:

三、使用命名空间成员的方法

        在引用命名空间成员时,要用命名空间名和作用域分辨符对命名空间成员进行限定,以区别不同的命名空间中的同名标识符,如:

命名空间名::命名空间成员名

        这种方法是有效的,并保证所引用的实体有惟一的名字。但是如果命名空间名字比较长,尤其在有命名空间嵌套的情况下,为引用一个实体,需要写很长的名字。为此,C++提供了一些机制,能简化使用命名空间成员的手续。

(1)使用命名空间别名

        可以为命名空间起一个别名(namespace alias),用来代替较长的命名空间名。例如下:

#include <iostream>
using namespace std;
namespace ns1{
	const double PI = 3.1415926;
	int age = 30;
	double area(){
		return 2 * 20 * PI;
	}
	namespace ns2{
		float wage = 1500.0f;
	}
}

int main(){
	cout <<ns1::PI <<endl;
	cout <<ns1::age <<endl;
	cout <<ns1::area() <<endl;
	// 用别名n2代替ns1::ns2
	namespace n2 = ns1::ns2;
	cout <<n2::wage <<endl;
	return 0;
}

        运行结果还是一样的,如下图:

(2)使用using命名空间成员

        using后面的命名空间成员名必须是由命名空间限定的名字。例如:

#include <iostream>
using namespace std;
namespace ns1{
	const double PI = 3.1415926;
	int age = 30;
	double area(){
		return 2 * 20 * PI;
	}
}

int main(){
	// 声明其后出现的变量或函数都是属于命名空间ns1中的
	using ns1::PI;
	using ns1::age;
	using ns1::area;
	// 此处引用相当于ns1::PI, ns1::age, ns1::area()
	cout <<PI <<endl;
	cout <<age <<endl;
	cout <<area() <<endl;
	return 0;
}

        当然,前面Student示例如,如使用using则会产生二义性,编译出错,代码如下:

#include <iostream>
#include "s1.h"
#include "s2.h"
using namespace std;

int main(){
	using ns1::Student;
	Student s1(100, "Tom", 20);
	// 错误,会出现二义性
	using ns2::Student;
	Student s2(1001, "John", 30, 1500.0f);
	// 打印结果信息
	s1.print();
	s2.print();
	return 0;
}

        所以要注意,在同一作用域中用using声明的不同命名空间的成员中不能有同名的成员。

(3)使用using namespace 命名空间名

        在上面介绍的using命名空间成员,一次只能声明一个命名空间成员,如果在一个命名空间中定义了多个实体,就需要使用多次using命名空间成员名。C++为此提供了using namespace 语句为实现只要用一个语句就能一次声明命名空间中全部成员。示例如下:

#include <iostream>
#include "s1.h"
using namespace std;
using namespace ns1;
int main(){
	Student s1(100, "Tom", 20);
	// 打印结果信息
	s1.print();
	return 0;
}

        运行结果如下图:

        当然,此用法同“(2)使用using命名空间成员”一样,使用多个命名空间时,当多个命名空间中出现同名时,容易出错。如下代码:

#include <iostream>
#include "s1.h"
#include "s2.h"
using namespace std;
using namespace ns1;
using namespace ns2;

int main(){
	Student s1(100, "Tom", 20);
	//错误,会出现二义性
	Student s2(1001, "John", 30, 1500.0f);
	// 打印结果信息
	s1.print();
	s2.print();
	return 0;
}

        此时编译时会报错【[Error] reference to 'Student' is ambiguous】- 因同一作用域中引入两个命名空间ns1和ns2,其中有同名的类,此时无法判定是哪个命名空间的Student,所以会出现二义性,编译出错。

四、无名的命名空间

        C++还允许使用没有名字的命名空间,如在文件中声明了以下无名命名空间,代码如下:

#include <iostream>
using namespace std;
// 定义无名命名空间
namespace{
	void test(){
		cout <<"Test...";
	}
}

int main(){
	test();
	return 0;
}

        运行结果如下图:

        由于命名空间没有名字,在其他文件中显然无法引用,它只在本文件的作用域内有效。其作用是更该函数的作用域限定于本文件。C++保留了用static声明函数的用法,同时提供了用无命名空间来实现这一功能,使用无命名空间成员的方法将会取代以前习惯用的对全局变量的静态声明。

五、标准命名空间std

        为了解决C++标准库中的标识符与程序中的全局标识符之间以及不同库中的标识符之间的同名冲突,应该将不同库的标识符在不同的命名空间中定义(或声明)。标准C++库的所有标识符都在一个名为std的命名空间中定义的,或者说标准头文件中函数、类、对象和类模板是在命名空间std中定义的。std是standard(标准)的缩写,表示这是存放标准库的有关内容的命名空间。

        在程序中用到C++标准库时,需要使用std作为限定,代码如下:

std::cout <<"OK" <<endl;

        C++介绍到这里,想必大家已了解命名空间的使用。这就是大家有时看到文件中未引用命名空间std时,标准库中的成员侧需要使用std引用,代码如下:

std::cout <<"Hello World" <<std::endl;

        当引用了命名空间std时,又可以省略掉std,代码如下:

using namespace std;

cout <<"Hello World" <<endl;

        所以在标准的C++编程中,应对命名空间std的成员进行声明或限定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1822325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# WPF入门学习主线篇(二十九)—— 绑定到对象和集合

C# WPF入门学习主线篇&#xff08;二十九&#xff09;—— 绑定到对象和集合 在WPF中&#xff0c;数据绑定是开发动态和交互性用户界面的核心技术。通过数据绑定&#xff0c;我们可以轻松地将UI控件与后台的数据源连接起来&#xff0c;实现数据的自动更新和显示。在本篇文章中&…

618有哪些值得入手的电子产品,个个都是心头爱!

今年的618购物节目已经开启&#xff01;你们期待的购物节就要到了&#xff0c;是不是已经跃跃欲试&#xff0c;准备开启购物模式了呢&#xff1f;别急&#xff0c;今天我就给大家带来了一份2024年618电子产品的好物清单&#xff0c;让你们购物不迷茫&#xff0c;轻松选到心仪的…

超声波清洗机对眼镜有伤害吗?四大超值不踩雷超声波清洗机安利

眼镜是现代人生活中的必备物品&#xff0c;但是很多人可能对于如何正确清洗眼镜感到困惑。传统的清洗方法可能会在清洗过程中对眼镜造成损坏&#xff0c;例如使用普通肥皂或清水清洗时容易划伤镜片。为了解决这个问题&#xff0c;家用眼镜超声波清洗机应运而生。超声波清洗机利…

逻辑斯谛回归与最大熵模型的原理实现

逻辑斯谛回归(LR)是经典的分类方法 1&#xff0e;逻辑斯谛回归模型是由以下条件概率分布表示的分类模型。逻辑斯谛回归模型可以用于二类或多类分类。 P ( Y k ∣ x ) exp ⁡ ( w k ⋅ x ) 1 ∑ k 1 K − 1 exp ⁡ ( w k ⋅ x ) , k 1 , 2 , ⋯ , K − 1 P(Yk | x)\frac{\…

RT-thread内核对象的基础应用

RT-thread的内核对象基础应用 启动流程&#xff1a; 以RT-Thread Studio为例&#xff0c;用户程序入口为位于 main.c 文件中 的main 函数。系统启动后先运行startup_stm32f103xe.s文件中的汇编代码&#xff0c;运行“bl entry”指令后跳转到components.c 文件中调用entry函数&a…

关于印发农业中央预算内投资专项管理办法的通知

国家发展改革委关于 印发农业中央预算内投资专项 管理办法的通知 发改农经规〔2024〕744号 农业农村部、海关总署、国家林草局&#xff0c;各省、自治区、直辖市及计划单列市、新疆生产建设兵团发展改革委&#xff0c;北大荒农垦集团有限公司&#xff1a; 为全面贯彻党的二十…

AI时代的程序员,复合型技术大咖该具备哪些本领与魅力?

AI时代对程序员和互联网时代对程序员的要求有不同 在AI时代的今天&#xff0c;程序员所面临的挑战已经有了翻天覆地的变化。 与互联网时代相比&#xff0c;AI时代对程序员的要求更为全面与多元化 回顾互联网时代&#xff0c;程序员主要需要掌握技术的专业知识和编程技能。他…

安卓/iOS/Linux系统影音边下边播P2P传输解决方案

在当今的数字时代&#xff0c;IPTV 影音行业正经历着快速的发展和变革&#xff0c;但影音行业的流量带宽成本一直很高&#xff0c;有没有什么办法既能保证现有的用户观看体验&#xff0c;又能很好降低流量带宽成本呢? P2P技术可能是一个很好的选择&#xff0c;它不仅仅可以提…

vue+showdown展示Markdown 文本

前言&#xff1a; vueshowdown展示Markdown 文本&#xff0c;资料整理 使用教程-vditor&#xff1a; 1、安装 npm install vditor --save 2、使用 <template><div id"vditor" name"description" ></div> </template> <scri…

Ransac(随机抽样一致性算法)多项式拟合附近的点

Ransac&#xff08;随机抽样一致性算法&#xff09;多项式拟合附近的点 RANSAC&#xff08;RANdom SAmple Consensus&#xff09;算法是一种用于拟合数学模型的迭代方法&#xff0c;尤其适用于对数据中有噪声的情况。RANSAC的核心思想是通过迭代从数据集中随机抽取一小部分样本…

计算机图形学入门11:图形管线与着色器

1.什么是图形管线 把场景中的物体经过一系列的处理&#xff0c;最后一张图像的形式在屏幕上显示出来&#xff0c;这一系列过程就是图形管线(Graphics Pipeline)&#xff0c;也叫实时渲染管线(Real-time Rendering Pipeline)。如下图所示&#xff0c;为整个渲染管线的过程。 渲染…

Python:从头创建 Asyncio (2)

引言 现在&#xff0c;asyncio 已成为 Python 社区中的热门话题&#xff0c;并且名副其实——它提供了一种非常出色的处理 I/O 密集型程序的方法&#xff01;在我探索 asyncio 的过程中&#xff0c;我起初并不太明白它的工作原理。但随着深入学习&#xff0c;我意识到 asyncio …

go interface

package mainimport "fmt"// 接口 interface func main() {c : Chinese{} //创建一个中国人实例u : American{} //创建一个美国人实例greet(c) //中国人打招呼greet(u) //美国人打招呼 }// 接收具备SayHello接口能力的变量 func greet(s SayHello) {…

sslh一键在一个端口上运行多个服务(KALI工具系列二十三)

目录 1、KALI LINUX 简介 2、sslh工具简介 3、信息收集 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、操作示例 4.1 监听特定端口 4.2 配置SSH 4.3 配置apache 4.4 配置sshl 4.5 验证配置 5、总结 1、KALI LINUX 简介 Kali Linux 是一个功能强大、…

腾讯云对象存储不绑定自定义备案域名不给下载应该如何处理?

从2024年1月1日起&#xff0c;腾讯云对象存储&#xff08;COS&#xff09;将实施新政策&#xff1a;新创建的存储桶不再支持使用path-style域名&#xff08;即存储桶绝对路径&#xff09;。此外&#xff0c;使用默认域名访问的新存储桶将不再支持任意类型文件的预览&#xff0c…

夏日炎炎 水域守护:北斗守护安全防线——为生命撑起智能保护伞

随着夏季的来临&#xff0c;炎热的天气让许多人纷纷寻求水的清凉。清凉的河流与广阔的海域成为了不少人消暑降温的向往之地。然而&#xff0c;私自下河、下海的行为却暗藏着巨大的安全隐患&#xff0c;每年夏季溺水事故频发&#xff0c;给无数家庭带来不可挽回的悲痛。为有效遏…

QT绘图项目 - 汽车表盘

目录 前言: 整体代码 widget.h widget.cpp 效果演示 实现刻度文字正确排版 优化代码 达到效果 封装整理代码结构: widget.h widget.cpp 指针样式美化 优化后的指针API 效果演示 设置高速刻度为红色 优化刻度API 效果演示 速度显示优化 给内圈画上黑色 优化速度…

【java计算机专业毕设】房屋租赁系统代码源码MySQL springboot vue html maven送文档ppt

1项目功能 【java计算机专业毕设】房屋租赁系统javaweb MySQL springboot vue html maven 送报告 2项目介绍 系统功能&#xff1a; 房屋租赁系统包括管理员和用户和房东三种角色。 该系统包含多个功能模块&#xff0c;分别为管理员、用户和房东提供服务。管理员功能包括个人中…

智能创作引领潮流,抓住时机!TikTok矩阵源码带来自动定时发布的成功策略

智能创作是当今社交媒体平台发展的重要趋势&#xff0c;而TikTok作为最受欢迎的短视频平台之一&#xff0c;通过其独特的创作方式和大量的用户&#xff0c;已经成为广告主和内容创作者的首选平台。在这个竞争激烈的市场&#xff0c;抓住时机并实现成功的关键是自动定时发布&…

遗传算法求解车间调度问题(附python代码)

背景介绍 车间调度问题&#xff08;Job Shop Scheduling Problem, JSSP&#xff09;是一类经典的组合优化问题&#xff0c;它在制造业和生产管理中有着广泛的应用。JSSP 的目标是对车间中的一系列作业进行排程&#xff0c;以使得作业在不同机器上的加工顺序是最优的&#xff0…