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

        命名空间是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的成员进行声明或限定。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue代办事件案例实战练习,配有答案解析

代办事件案例 该案例&#xff0c;综合了前面所学的知识&#xff0c;列入点击事件绑定&#xff0c;双向绑定&#xff0c;v-for循环语句&#xff0c;v-model双向绑定&#xff0c;以及input标签的不同type形式。 演示代码如下&#xff1a; <template > <div id"ku…

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

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

刷题记录(240613)

aliyun0512 1. 小红定义一个数组是好数组&#xff0c;当且仅当所有奇数出现了奇数次&#xff0c;所有偶数出现了偶数次。现在小红拿到了一个数组&#xff0c;她希望取一个该数组的非空子序列(可以不连续)&#xff0c;使得子序列是好数组。你能帮小红求出子序列的方案数吗?由于…

C++面向对象:多态性

多态性 1.概念 多态性是面向对象的程序设计的一个重要特征。在面向对象的方法中一般是这样表述多态的&#xff1a;向不同的对象发送同一个信息&#xff0c;不同的对象在接收时会产生不同的行为。也就是说&#xff0c;每个对象用自己的方式去响应共同的消息。 2.典例 下面这…

MFC动态创建按钮

void CMFCApplication1Dlg::OnBnClickedOk() {for (int i 0; i < 100; i){for (int j 0; j < 100; j){CButton* pButton3 new CButton;pButton[i][j] pButton3;}}CRect rect;GetClientRect(&rect); // 获取对话框客户区的大小rect.top 10; // 设置按钮的位置rec…

Elastic 索引结构-倒排索引

前言 Elastic 在数据库分类中一般被分为全文检索的数据库&#xff0c;那为什么这么区分呢&#xff1f;主要是因为其独特的索引结构 即倒排索引。 倒排索引 倒排索引先将文档中包含的关键字全部提取出来&#xff0c;然后再将关键字与文档的对应关系保存起来&#xff0c;最后再…

19、24年--信息系统工程——安全工程

1、工程概述 信息安全系统工程就是要建造一个信息安全系统,它是整个信息系统工程的一部分,而且最好是业务应用信息系统工程同步进行,主要围绕信息安全内容。 2、安全系统 1)X轴是”安全机制“。安全机制可以理解为提供某些安全服务,利用各种安全技术和技巧,所形成的一个…

06 SpringBoot 配置文件详解-application.yaml

Spring Boot 提供了大量的自动配置&#xff0c;极大地简化了spring 应用的开发过程&#xff0c;当用户创建了一个 Spring Boot 项目后&#xff0c;即使不进行任何配置&#xff0c;该项目也能顺利的运行起来。当然&#xff0c;用户也可以根据自身的需要使用配置文件修改 Spring …

电脑技巧:认识全能绘画软件Krita

目录 一、软件简介 二、软件功能 2.1 强大的画笔引擎 2.2专业色彩管理 2.3 多层编辑与管理 2.4 动画制作 三、软件特点 四、安装说明 五、使用技巧 六、快捷键大全 对于喜欢绘画的朋友来说&#xff0c;Krita 是一款不可多得的绘画工具&#xff0c;它具有开源、免费、…

查分易发成绩教程

马上就要期末考试了&#xff0c;老师们是不是正为家长咨询成绩倍感头痛&#xff1f;在以前老师们发布成绩都是私发给家长或者写在一张小纸条上让学生带回家&#xff0c;麻烦还容易出错&#xff0c;给老师的工作带来不小的压力。不过现在的年轻教师都在使用——查分易小程序&…

开源项目QAnything:全能型本地知识库问答系统

在当今信息爆炸的时代&#xff0c;如何高效地管理和检索大量数据成为了一个重要课题。网易有道推出的开源项目QAnything&#xff0c;正是为了解决这一问题而生。QAnything是一个本地知识库问答系统&#xff0c;支持多种文件格式和数据库&#xff0c;允许用户在离线状态下进行安…

Linux:线程概念 线程控制

Linux&#xff1a;线程概念 & 线程控制 线程概念轻量级进程 LWP页表 线程控制POSIX 线程库 - ptherad线程创建pthread_createpthread_self 线程退出pthread_exitpthread_cancelpthread_joinpthread_detach 线程架构线程与地址空间线程与pthread动态库 线程的优缺点 线程概念…

复分析——第2章——Cauchy定理及其应用(E.M. Stein R. Shakarchi)

第2章 Cauchy定理及其应用 The solution of a large number of problems can be reduced, in the last analysis, to the evaluation of definite integrals; thus mathematicians have been much occupied with this task... However, among many results obtained, a n…

【RabbitMQ】初识 RabbitMQ

初识 RabbitMQ 1.认识 RabbitMQ1.1 介绍1. 2.使用场景1.2.1 推送通知1.2.2 异步任务1.2.3 多平台应用的通信1.2.4 消息延迟1.2.5 远程过程调用 1.3 特性 2.基本概念2.1 生产者、消费者和代理2.2 消息队列2.3 交换机2.3.1 direct2.3.2 topic2.3.3 headers2.3.4 fanout 2.4 绑定2…

基于SpringBoot+VueBBS论坛系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

蓝牙模块的工作原理与电路设计

蓝牙技术是一种短距离无线通信技术&#xff0c;广泛应用于各种智能设备中&#xff0c;如手机、耳机、智能手表等。蓝牙模块作为实现蓝牙通信的核心部件&#xff0c;其工作原理和电路设计对于蓝牙设备的性能和稳定性至关重要。本文将深入解析蓝牙模块的工作原理&#xff0c;包括…

Docker(一)-认识Docker

1.docker理念 Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build,Ship and Run Any App,Anywhere”&#xff0c;也就是通过对应用组件的封装&#xff0c;分发&#xff0c;部署&#xff0c;运行等生命周期的管理&#xff0c;使用户的应用及其运行环境能够做到”…

18.1 HTTP服务器-极简服务器、请求与响应

1. 极简服务器 大道至简。使用Go语言构建世界上最简单的HTTP服务器&#xff0c;仅需四行代码。 标准库的net/http包提供了多种用于创建HTTP服务器的方法&#xff0c;其中包括&#xff1a; http.HandleFunc("/", rootHandler) 第一参数&#xff1a;访问的url 第二…

Elasticsearch搜索引擎(高级篇)

3.1 查询语法 | 《ElasticSearch入门到实战》电子书 (chaosopen.cn) day09-Elasticsearch02 - 飞书云文档 (feishu.cn) 目录 第一章 DSL查询 1.1 基本语法 1.2 叶子查询 全文检索查询 精确查询 1.3 复合查询 算分函数查询 bool查询 1.4 排序 1.5 分页 基础分页 深度分…

数据可视化:Seaborn

安装Seaborn 进入虚拟环境&#xff0c;在终端中键入 pip install seaborn 即可安装。 初步使用Seaborn 在使用seaborn之前&#xff0c;我们先了解一下seaborn是什么&#xff0c;seaborn是以matplotlib为底层的更简便的python第三方库&#xff0c;它可以更快捷地去设置图形的一…