C++命名空间

目的:

     * 掌握命名空间的作用及定义,如何使用命名空间。

一、 为什么需要命名空间

命名空间是ANSI C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突
在C语言中定义了3个层次的作用域,即文件(编译单元)、函数和复合语句。C++又引入了类作用域,类是出现在文件内的。在不同的作用域中可以定义相同名字的变量,互不于扰,系统能够区别它们。

由于各头文件可能是由不同的人设计的,有可能在不同的头文件中用了相同的名字来命名所定义的类或函数
如:程序员甲在头文件headerl.h中定义了类Student和函数fun。

#include <string>
#include <cmath>
using namespace std;
class Student //声明Student类
{ 
public:
     Student(string nam,int a)
       { name=nam;age = a;}
     void get_data();
private:
     string name;
     int age;
};
void Student::get_data() //成员函数定义
{ 
    cout<<name<<endl; 
}

double fun(double a,double b)//定义全局函数(即外部函数)
{
    return sqrt(a+b);
}
程序员乙写了头文件header2.h,在其中同样定义了类Student和函数fun,但其内容与头文件headerl.h中的Student和函数fun有所不同。
#include <string>
#include <cmath>
using namespace std;
class Student //声明Student类
{ 
public:
     Student(string nam,char s) //参数与headerl中的student不同
     { name=nam;sex=s;}
     void get_data();
private:
     string name;
     char sex; //此项与headerl不同
};
void Student::get_data() //成员函数定义
{ 
    cout<<name<<" "<<sex<<endl; 
}

double fun(double a,double b) //定义全局函数 
{ 
    return sqrt(a-b);//返回值与headerl中的fun函数不同
} 
 假如程序员在其程序中要用到headerl.h中的Student和函数fun,因而在程序中包含了头文件headerl.h。同时要用到头文件header2.h中的一些内容(但对header2.h中包含与headerl.h中的Student类和fun函数同名而内容不同的类和函数并不知情),因而在程序中又包含了头文件header2.h。

如果主文件(包含主函数的文件)如下:

#include <iostream>
using namespace std;
#include "header1.h"//包含头文件l
#include "header2.h"//包含头文件2
int main()
{ 
    Student stud1("Wang",18);
    stud1.get_data();
    cout<<fun(5,3)<<endl;
    return 0;
}
这时程序编译就会出错。因为在预编译后,头文件中的内容取代了对应的#include命令行,这样就在同一个程序文件中出现了两个Student类和两个fun函数,显然是重复定义

二、 什么是命名空间

    命名空间:实际上就是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他命名空间中的全局实体分隔开来。如:

namespace ns1 //指定命名中间nsl
{ 
    int a;
    double b; 
} //没有分号
namespace是关键字,nsl是用户自己指定的命名空间的名字(这里用ns1是因为ns是namespace的缩写,含义请楚)。现在命名空间成员包括变量a和b,注意a和b仍然是全局变量。如果在程序中要使用变量a和b,必须加上命名空间名和作用域分辨符“::”,如nsl::a,nsl::b。这种用法称为命名空间限定(qualified),这些名字(如nsl::a)称为被限定名(qualified name)。
命名空间的花括号内不仅可以包括变量,而且还可以包括以下类型
·变量(可以带有初始化);
·常量; 
·数(可以是定义或声明);
·结构体;
·类;
·模板;
·命名空间(在一个命名空间中又定义一个命名空间,即嵌套的命名空间)。

注意:在头文件中,不要把#include命令放在命名空间中

如:

namespace nsl
{ 
    const int RATE=0.08; //常量
    double pay;       //变量
    double tax()       //函数
    {
        return a*RATE;
    }
    namespacens2       //嵌套的命名空间
    {
        int age;
    }
} 
如果想输出命名空间nsl中成员的数据,可以采用下面的方法:
cout<< nsl::RATE << endl;
cout<< nsl::pay << endl;
cout<< nsl::tax() << endl;
cout<< nsl::ns2::age << endl;

三、 使用命名空间解决名字冲突

现在利用命名空间解决程序中名字冲突问题。修改两个头文件,把在头文件中声明的类分别放在两个不同的命名空间中。
头文件headerl修改为:

using namespace std;
#include <string>
#include <cmath>
namespace ns1 //声明命名空间ns1
{ 

class Student //在命名空间nsl内声明Student类 
{ 
    。。。
};
void Student::get_data() //定义成员函数
{ 
    。。。
}

double fun(double a,double b) //在命名空间n引内定义fun函数
{ 
    。。。
}

}
头文件header2修改为:
#include <string>
#include <cmath>
namespace ns2 //声明命名空间ns2
{ 

class Student
{ 
    。。。
}
void Student::get_data()
{
    。。。
}

double fun(double a,double b)
{
    。。。
}

}
调用程序可改为:

#include <iostream>
#include "header1.h" //包含头文件l
#include "header2.h" //包含头文件2
int main()
{ 
    ns1::Student stud1("Wang",18);//用命名空间nsl中声明的Student类定义studt
    stud1.get_data(); //不要写成ns1::st udl.get_data(); 
    cout<<Ns1::fun(5,3)<<endl; //调用命名空间ns1中的fun函数

    ns2::Student stud2(102,"Li",'f'); //用命名空间ns2中声明的Student类定义stud2
    stud2.get_data();
    cout<<ns2::fun(5,3)<<endl; //调用命名空间nsl,中的fun函数
    return 0; 
}

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

从上面的介绍可以知道,在引用命名空间成员时,要用命名空间名和::对命名空间成员进行限定,以区别不同的命名空间中的同名标识符。即:
命名空间名::命名空间成员名
但如果命名空间名字比较长,尤其在有命名空间嵌套的情况下,为引用一个实体,需要写很长的名字。在一个程序中可能要多次引用命名空间成员,就会感到很不方便。

1 、使用命名空间别名
可以为命名空间起一个别名(namespace alias),用来代替较长的命名空间名。如
namespace Television //声明命名空间,名为Television
{ ... }
可以用一个较短而易记的别名代替它。如:

namespace TV=Television; //别名TV与原名Television等价,在原来出现Television的位置都可以无条件地用TV来代替。

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

using nsl::Student;
则在其后程序中出现的Student就是隐含地指nsl::Student。

3、使用using namespace命名空间名
用上面介绍的using命名空间成员名,一次只能声明一个命名空间成员,如果在一个命名空间中定义了10个实体,就需要使用10次using命名空间成员名。能否在程序中用一个语句就能一次声明一个命名空间中的全部成员呢?C++提供了using namespace语句来实现这一目的。using namespace语句的一般格式为
using namespace 命名空间名;

如:

using nanlespace nsl;
声明了在本作用域中要用到命名空间nsl中的成员,在使用该命名空间的任何成员时都不必用命名空间限定。

注意:

如果都用using声明,也会冲突。如:

usmgnsl::Student; //声明其后出现的Student是命名空间nsl中的Student
usmgns2::Student; //声明其后出现的Student是命名空间ns2小的Student
Student stud1; //冲突,无法确定用哪一个空间中的Student

五、 无名的命名空间

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

namespace //命名空间没有名字
{ 
    void fun( ) //定义命名空间成员
    { 
        cout<<"OK."<<endl;
    }
}
由于命名空间没有名字,在其他文件中显然无法引用,它只在本文件的作用域内有效。无名命名空间的成员fun函数的作用域为文件A(确切地说,是从声明无名命名空间的位置开始到文件A结束)。在文件A中使用无名命名空间的成员,不必(也无法)用命名空间名限定。
可以联想到:在C浯言中可以用static声明一个函数,其作用也是使该函数的作用域限于本文件。C++保留了用static声明函数的用法,同时提供了用无名命名空间来实现这一功能。

六、标准命名空间std

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

std::cout<<"OK."<<endl; //声明cout是在命名空间std中定义的流对象
大多数的C++程序中常用using namespace std语句对命名空间std进行声明,这样可以不必对每个命名空间成员一进行处理。这样,在std中定义和声明的所有标识符在本文件中都可以作为全局量来使用。但是应当绝对保证在程序中不出现与命名空间std的成员同名的标识符,例如在程序中不能再定义一个名为cout 的对象。由于在命名空间std中定义的实体实在太多,有时程序设计人员也弄不请哪些标识符已在命名空间std中定义过,为减少出错机会,有的专业人员喜欢用若干个"using命名空间成员”声明来代替“using namespace命名空间”声明,如
using Std::string;
using Std::cout;
using Std::cin;
为了减少在每一个程序中都要重复书写以前的using声明,程序开发者往往把编写应用程序时经常会用到的命名空间std成员的using声明组成一个头文件,然后在程序中包含此头文件即可。




















豌豆代理(又称豌豆 IP)是一款一站式国内代理 IP 服务平台,主打高匿名、低延迟、高可用的 IP 资源,支持 HTTP/HTTPS/SOCKS5 协议,适配 Windows、Mac、Android、iOS 多平台。 多类型 IP 资源与高覆盖节点 提供动态住宅 IP、静态独享 IP、数据中心 IP,覆盖全国 200 + 城市,可用率 99%+;支持省市精准选择或全国混拨,适配不同业务合规与稳定性需求。 使用:在客户端 “节点 / 线路” 页,按城市 / 类型筛选,一键连接目标 IP,适合爬虫、电商多账号运营等场景。 秒级 IP 切换与灵活调度 支持手动一键切换、秒级动态切换(切换速度低至 100ms)、定时切换(自定义时长),并自动过滤重复 IP,避免重复使用导致风险。 使用:在 “设置” 中开启 “自动切换” 并设时间间隔,或按 Ctrl+Q 快捷键一键换 IP,适配反爬虫、批量测试等高频切换场景。 全协议支持与多端适配 兼容 HTTP/HTTPS/SOCKS5 主流代理协议,可对接浏览器、爬虫脚本、客户端软件;支持 Windows、Mac、安卓、iOS 多端同步使用,跨设备无缝切换。 使用:在客户端 “协议设置” 选择对应协议,生成代理地址与端口,直接填入目标软件即可生效。 隐私安全与数据加密 自研传输加密技术保护数据传输,搭配高匿名 IP 隐藏真实地址,同时支持自动清除 Cookie / 缓存,降低隐私泄露与追踪风险。 使用:在 “安全设置” 中开启 “数据加密” 与 “自动清理缓存”,公共 WiFi 环境下优先启用,提升隐私防护等级。 智能筛选与稳定网络优化 系统自动筛选低延迟、高可用 IP,过滤失效 / 重复地址;依托自建纯净机房与独享带宽,搭配 BGP 多线接入,保障连接稳定性与速度。 使用:无需手动配置,客户端默认智能匹配合适节点,复杂网络环境可在 “网络
在网络高速发展的时代,众多的软件被开发出来,给用户带来了很大的选择余地,而且人们越来越追求更个性的需求。在这种时代背景下,商家只能以用户为导向,以商品的持续创新作为商家最重要的事项。 在新发展的时代,人们对幼儿资源互助共享平台越来越重视,才能实现幼儿资源互助共享平台的有效发挥,本文将通过幼儿资源互助共享平台的信息,分析在日常生活中对幼儿资源互助共享平台存在哪些问题探讨出进一步提升效率,管理能力的对策。 系统采用了Java技术,将所有模块采用以浏览器交互的模式,选择MySQL作为系统的数据库,来进行系统的设计。基本实现了幼儿资源互助共享平台应有的主要功能模块,本系统有管理员:首页、个人中心、用户管理、卖家管理、咨询师管理、萌宝信息管理、幼儿知识管理、保姆推荐管理、音频资源管理、二手商品管理、商品分类管理、资源分类管理、交流论坛、系统管理,用户;首页、个人中心、萌宝信息管理、保姆推荐管理、音频资源管理,卖家;首页、个人中心、二手商品管理、订单管理,咨询师;首页、个人中心、幼儿知识管理,前台首页;首页、萌宝信息、幼儿知识、保姆推荐、音频资源、二手商品、交流论坛、个人中心、后台管理、购物车等功能。 对系统进行测试后,改善了程序逻辑和代码。同时确保系统中所有的程序都能正常运行,所有的功能都能操作,本系统的开发获取幼儿资源互助共享平台信息能够更加方便快捷,同时也使幼儿资源互助共享平台信息变的更加系统化、有序化。系统界面较友好,易于操作。
### C++ 命名空间的使用方法 #### 什么是命名空间命名空间是一种用于组织代码的方式,它能够防止全局范围内的名字冲突。通过定义不同的命名空间,可以在同一个程序中安全地重用相同的标识符名称。 #### 定义命名空间 可以通过 `namespace` 关键字来创建一个新的命名空间。例如: ```cpp namespace MyNamespace { int value = 42; } ``` 在此例子中,`MyNamespace` 是一个自定义命名空间,其中包含了一个整型变量 `value`[^1]。 #### 访问命名空间中的成员 要访问命名空间中的成员,可以使用作用域解析运算符 `::`。例如: ```cpp #include <iostream> namespace N { int a = 10; } int main() { std::cout << N::a << std::endl; // 输出 10 return 0; } ``` 上述代码展示了如何通过 `N::a` 来访问命名空间 `N` 中的变量 `a`[^2]。 #### 使用 `using` 指令简化访问 当频繁使用某命名空间的内容时,可以利用 `using namespace` 将整个命名空间引入当前作用域。这样就不必每次都显式指定命名空间前缀。例如: ```cpp #include <iostream> using namespace std; int main() { cout << "Hello, world!" << endl; // 不需要写成 std::cout return 0; } ``` 这里通过 `using namespace std;` 的声明省去了每次调用标准库函数或对象时都需要加上 `std::` 的麻烦。 #### 局部导入特定成员 除了将整个命名空间引入外,还可以仅导入某些特定的成员到当前作用域。这有助于减少潜在的名字污染风险。例如: ```cpp #include <iostream> using std::cout; using std::endl; int main() { cout << "Only specific members are imported." << endl; return 0; } ``` 此方式只把 `std::cout` 和 `std::endl` 导入到了当前文件的作用域里。 #### 嵌套命名空间 C++ 支持嵌套命名空间的概念,允许在一个命名空间内部再定义另一个命名空间。这种结构可以帮助进一步分类和管理复杂的项目逻辑。如下所示: ```cpp namespace Outer { int outerValue = 1; namespace Inner { int innerValue = 2; } } int main() { std::cout << Outer::outerValue << ", " << Outer::Inner::innerValue << std::endl; return 0; } ``` 这段代码演示了如何处理多层嵌套的情况以及如何逐级访问这些深层嵌套的对象属性。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值