C++基础知识之命名空间namespace

命名空间使用动机

大型项目开发中会用到很多独立开发的库,很可能会出现不同库中命名相同的函数或者模板等,当然可以通过增加起名复杂度来规避,但并非良策,因此命名空间油然而生,它可以解决命名冲突的情况,它将全局命名空间分割成一个个作用域,从而来避免命名空间污染
简单举例:

命名空间的创建如下:

namespace 命名空间名称{
//所属成员
}

namespace GUi{
    
    
	class Windows;
}
namespace statistics{
    
    
	class Windows;
}

虽然两个命名空间中成员的名称相同,但是不同命名空间的作用域不同,所以不会产生冲突

std::cin std::cout std::endl

初学C++应该对以上三句不陌生

首先认识一个操作符:::域操作符

::域操作符代表的意思是:从域操作符左侧名字所示的作用域中找出右侧的那个名字
std::cin的含义是使用命名空间std中的名字cin

std就是一个命名空间,可以搭配using关键字使用

我们在程序中随意使用cin cout endl等都不加std::,是因为我们在程序开头加了一句如下的代码:

using namespace std;

这句代码加入之后,只要是std命名空间中的名字都可以直接使用,无须再加专门的前缀。但其实最开始我们都是按照每个using声明引入命名空间中的一个成员的的原则来的,比如在程序使用如下语句:

std::cout << "你真帅呀阿杜" << std::endl;

我们都是按照以下模板进行声明的:

using namespace::name
(声明了上述语句,就可以使用命名空间namespace中的名字name)

即:

using std::cout
using std::endl

之后便可大胆使用如下代码:

cout << "你真帅呀阿杜" << endl;

但是:
using std::cout
using std::endl
以上两种声明只能在使用cout和endl时不用加前缀,而在用std中的string的时候还是要加前缀的(std::string),如果使用using namespace std;的话就不需要了,直接string

其实上述体现成代码的形式就是如下的形式:

namespace std{
    
    
	cin;
	cout;
	endl;
	stirng;
	……
}

int main(void){
    
    
	using namespace std;
	cout << *** << endl;
}

using namespace和using的区别

在C++中,using namespaceusing是用于命名空间的两种不同方式。

专业术语:
using namespace叫using指示

using叫using声明

using指示一次性注入某命名空间中的所有名字

using声明一次只能引入一个命名空间中的成员变量


例如:using namespace org::cyclonedds;

这是使用命名空间的一种方式,用于指定当前作用域中使用的命名空间。通过使用using namespace,我们可以省略使用该命名空间中的类、函数和变量时需要加上的命名空间前缀,以简化代码。
对于using namespace org::cyclonedds来说,它将整个org::cyclonedds命名空间中的所有成员引入到当前作用域中,使得我们可以直接使用该命名空间中的类、函数和变量,而无需在使用时加上org::cyclonedds前缀。

大白话的意思就是:在这种声明方式下org::cyclonedds是一个命名空间

namespace org{
    
    
	namespace cyclonedds{
    
    
		//命名空间中的各种成员,比如A、B、C
		//那么在使用ABC的时候不需要加前缀org::cyclonedds A,直接A就行
	}
}

using org::cyclonedds

这是使用命名空间中特定成员的一种方式,用于指定当前作用域中使用命名空间中的特定成员。通过使用using我们可以选择性地引入命名空间中的某个或某些成员,而不是整个命名空间
对于using org::cyclonedds来说,它只引入了org命名空间中的一个成员cyclonedds,而不是整个命名空间。这样,我们只能直接使用被引入的特定成员,其他未引入的成员仍然需要加上相应的命名空间前缀来使用


综上所述,using namespace org::cyclonedds引入了整个org::cyclonedds命名空间中的所有成员,而using org::cyclonedds只引入了该命名空间中的特定成员。它们都可以简化代码,并使得我们可以直接使用命名空间中的成员而无需加上命名空间前缀。

using 指示和using声明的区别进行举例验证

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;

int num = 900;
int num1 = 1000;

namespace org{
    
    
        namespace eclipse{
    
    
                namespace duzhognbo{
    
    
                        int num = 100;
                }
        }
}
//自定义的命名空间要在其using namespace之前才行
namespace org1{
    
    
        namespace eclipse1{
    
    
                namespace duzhognbo1{
    
    
                        int num2 = 100;
                        string name = "zhongguo";
                }
        }
}
using namespace org1::eclipse1::duzhognbo1;//只有这么引入才可直接使用name和num2
using org1::eclipse1::duzhognbo1::name;//只是引入了命名空间中的特定成员name,name可直接使用,num2不可
int main(void) {
    
    
        cout << "num = " << num << endl;//num = 900
        cout << "num = " << org::eclipse::duzhognbo::num << endl;// num = 100
        cout << "name = " << name << endl;
        cout << "num2 =" << num2 << endl;
        system("pause");
        return 0;
}

分析:
1、cout << "num = " << num << endl;直接调用使用的是全局变量num,只有org::eclipse::duzhognbo::num时才调用命名空间org::eclipse::duzhognbo中的num值

2、using namespace org1::eclipse1::duzhognbo1是引入命名空间中的所有成员,它里面的任何成员的使用都不需要加前缀,例如name、num2

3、using org1::eclipse1::duzhognbo1::name;//只是引入了命名空间中的特定成员name,name可直接使用,num2不可

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
//自定义的命名空间要在其using namespace之前才行
namespace org1{
    
    
        namespace eclipse1{
    
    
                namespace duzhognbo1{
    
    
                        int num2 = 100;
                        string name = "zhongguo";
                }
        }
}
using namespace org1::eclipse1;
int main(void) {
    
    
        cout << "name = " << duzhognbo1::name << endl;//name = zhongguo
        cout << "num2 =" << duzhognbo1::num2 << endl;//num2 = 100
        system("pause");
        return 0;
}

using namespace org1::eclipse1;是引入org1::eclipse1这个命名空间中的所有成员,所以访问name和num2的时候需要duzhognbo1::nameduzhognbo1::num2

总结
1、只要有using namespace关键词出现,就直接引入某个命名空间的全部成员
2、如果只有using的话,就是加入特定的成员
3、如果没有using或者using namespace,直接在程序用org1::eclipse1::duzhognbo1::name这种形式,说明直接访问命名空间中的成员了,没有引入特定成员或者全部成员

namespace的常见用法举例

1、基本用法:

namespace MyNamespace {
    
    
    int x;
    void func() {
    
    
        // 函数实现
    }
}
int main() {
    
    
    MyNamespace::x = 10;
    MyNamespace::func();
    return 0;
}

2、嵌套命名空间(注意访问方法)

namespace Outer {
    
    
    int x;
    namespace Inner {
    
    
        int y;
    }
}
int main() {
    
    
    Outer::x = 10;
    Outer::Inner::y = 20;
    return 0;
}

3、使用别名

namespace MyNamespace {
    
    
    int x;
    void func() {
    
    
        // 函数实现
    }
}
namespace ns = MyNamespace;
int main() {
    
    
    ns::x = 10;
    ns::func();
    return 0;
}

namespace ns = MyNamespace;可以为复杂的命名空间起一个简洁的名字ns

当然也可以为嵌套的命名空间起别名

namespace MyNamespace {
namespace MyNamespace222 {

}}
namespace ns = MyNamespace::MyNamespace222;

4、命名空间的拓展

namespace MyNamespace {
    
    
    int x;
}
namespace MyNamespace {
    
      // 扩展命名空间
    void func() {
    
    
        // 函数实现
    }
}
int main() {
    
    
    MyNamespace::x = 10;
    MyNamespace::func();
    return 0;
}

注意:

namespace 命名空间名称 {
// 成员
}

创建一个新的命名空间或者在已经存在的命名空间中添加新成员的声明

using指示命名空间成员与其他变量冲突的解决方法

请添加图片描述

命名空间bilp中的所有成员被using指示代码(using namespace blip)全部注入,这个时候空间中的 j 与全局变量 j 重复,通过::j来代表全局变量,通过blip::j来代表命名空间中 j 来进行区分。

main中定义了一个局部变量 k 将覆盖 blip 命名空间中的 k

using指示是否可以多使用?

请添加图片描述

猜你喜欢

转载自blog.csdn.net/qq_42595610/article/details/131788359