栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

从C到C++

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从C到C++

名称空间 1. 背景

声明区域(declaration region):可以进行声明的区域。
全局变量的声明区是整个文件,函数内声明的变量的声明区是代码块。

潜在作用域(potential scope):声明位置开始到声明区截止。
作用域(scope):变量对程序的可见范围。
变量的作用域是潜在作用域的子集。
例如,在函数中声明的局部变量会隐藏同名的全局变量,导致全局变量的作用域缺少一部分。

名称空间(namespace):每个声明区都可以声明名称,并且这些名称独立于其他声明区的名称。(例如:一个函数中的局部变量不会和另一个函数的局部变量发生冲突。)所以说,每个声明区就是一个名称空间。
C++允许我们自己创造名称空间。为了统一概念,我们不再把代码块当成名称空间,所以名称空间只有两种:全局名称空间 用户创造的名称空间

2. 名称空间

我们创造两个名称空间Jack和Jill

int Hill;
namespace Jack{
    double pail;
    void fetch();
    int pal;
    struct well{...};
}
namespace Jill{
    double bucket(double n);
    double fetch;
    int pal;
    struct Hill{...};
}
2.1 名称空间的法则
  1. 名称空间只有两种:全局名称空间 用户创造的名称空间
  2. 全局名称空间是最基本的名称空间是。全局名称空间就是整个文件。对于其他的名称空间来说,它们存在的位置是:只能嵌套在另一个名称空间中,但是不能位于代码块中。
    换句话说,名称空间要么是全局名称空间,要么就是嵌套在另一个名称空间中,但是不能位于代码块中。
  3. 任何名称空间中的名称不会和其他名称空间中的名称发生冲突,例如,Jack中的fetch不会和Jill中的fetch发生冲突,Jill中的Hill不会和全局变量Hill发生冲突。
  4. 默认情况下,名称空间中的名称具有外部链接性和静态持续性。当然了,在全局名称空间中,我们有局部变量、全局变量、静态局部变量(内部链接性的静态变量),那么我们也可以在用户创造的名称空间中设置相应的变量。如果你对这些名词不熟悉可以看看我写的这篇博客。内存模型
  5. 用户创造的名称空间的一切声明和定义法则和全局名称空间一样。例如,我们也可以像全局名称空间那样,给jack名称空间,添加变量,添加函数定义,等等所有操作
namespace Jack{
    int extra;
}
namespace Jack{
    void fetch(){
        std::cout<<"hellon";
    }
}

那么,既然名称空间这么多,我们如何在一个名称空间中使用其他名称空间中的名称呢?作用域解析符——::,正如上面这段代码中所示,我们使用了std空间中的cout名称。

2.2 语法细谈 2.2.1 using声明
#include
namespace Jill{
    double bucket(double n);
    double fetch=0;
    int pal;
}
double fetch=2.222;
void foo();
int main(){
    using Jill::fetch;
    foo();
    std::cout<<"in main fetch : "< 
in foo fetch : 1.111
in main fetch : 1.111
global fetch : 2.222

这里的using Jill::fetch;就是我们所谓的 using声明,他使得main函数中的一切fetch名称都视为是Jill::fetch。这里的fetch会覆盖同名的全局变量,如果我们想要调用全局变量,只需要添加作用域解析符,::fetch就是全局变量,我们还验证了一个法则,默认情况下,Jill名称空间中的名称的持续性都是静态的,因为在foo函数中对fetch的修改,会影响main函数中的fetch的值。

#include
namespace Jill{
    double bucket(double n);
    double fetch=0;
    int pal;
}
using Jill::fetch;
void foo();
int main(){
    foo();
    std::cout<<"in main fetch : "< 

上面这段代码是正确的,我们把using声明放到了全局名称空间中,这样子全局名称空间的main函数中使用的fetch就是Jill::fetch。

2.2.2 using编译指令
#include
using namespace std;
int main(){
    cout<<"hello world!n";
}

上面这段代码就是最简单的C++程序,这里的#include会把头文件iostream放到std名称空间中,using namespace std;就是所谓的 using编译指令,上面那段代码会使得 std名称空间的所有名称在全局名称空间中可用。

#include
int main(){
    using namespace std;
    cout<<"hello world!n";
}

有的程序员喜欢上面这段代码,因为他使得 std名称空间中的所有名称在main()函数中可用,这种写法更加安全。

  • using声明使一个名称可用,而using编译指令使得所有的名称都可用。
  • using编译指令增加了名称冲突的可能性
namespace Jack{
    double pail;
    void fetch();
    int pal;
    struct well{...};
}
namespace Jill{
    double bucket(double n);
    double fetch;
    int pal;
    struct Hill{...};
}
using namespace Jack;
using namespace Jill;

上面这段代码会报错,因为他会将Jack和Jill中的所有名称导出到全局名称空间,从而引发fetch和pal名称的冲突。

2.2.4 using声明和using编译指令的比较

假设名称空间和声明区域定义了相同的名称。如果使用using声明,将名称空间中的名称导入声明区域,会导致两个名称发生冲突,从而报错。如果使用using编译指令将名称空间中的所有名称导入声明区域,不会报错也不会发出警告,因为局部名称会隐藏名称空间中的名称。

#include
namespace Jill{
    double bucket(double n);
    double fetch=0;
    int pal;
}
double fetch=1.11;
void foo();
int main(){
    using namespace Jill;
    char fetch[10]="hello";
    std::cout< 
hello
0
1.11
in foo fetch : 1.11

仔细看上面这段代码,很神奇是不是,它不会报错,这里有3个fetch:全局fetch,Jill名称空间中的fetch和局部变量fetch,在mian函数中使用using namespace Jill;不会报错,因为这里局部名称会隐藏名称空间名称和全局名称。如果把using namespace Jill;改成using Jill::fetch就会报错。

  • using声明像是声明了一个名称,它会与同名的局部名称发生冲突。
  • using编译指令更像是名称解析,它导入大量的名称,如果存在同名局部名称,则局部名称会覆盖名称空间名称。

using声明比using编译指令更安全

2.2.5 名称空间的嵌套
namespace Jill{
    double bucket(double n);
    double fetch=0;
    int pal;
}
namespace elements{
    namespace fire{
        int flame;
    }
}
namespace myth{
    using namespace elements;
    using std::cin;
    using std::cout;
    using Jill::fetch;
}

名称空间中仍然可以创造名称空间,使用using声明和using编译指令。

using namespace myth;
cin>>fetch;
cin>>fire::flame;

而且using编译指令具有传递性,所以using namespace myth;也会把elements名称空间中的所有名称导入全局名称空间。
所以cin>>fire::flame;也是合法的。
也可以给名称空间创造别名
namespace favorite=elements::fire;
using favorite::flame;

2.2.6 未命名的名称空间

未命名的名称空间中的变量是静态全局变量的替代品;

#include
static int count;
void foo();
int main(){
    using namespace std;
    foo();
    cout<<"now :"< 
now :1
now :2
now :3

上面这段代码等价于下面这段代码:

#include
namespace{
    int count;
}
void foo();
int main(){
    using namespace std;
    foo();
    cout<<"now :"< 

namespace{int count;}就好像后面跟着一条using编译指令一样,由于名称空间没有名字,所以在其他文件中使用using编译指令或者using声明。

3. 一些建议

名称空间的诞生是因为大型编程项目难于管理。如果你只写一些简单的程序请忽视下列建议。

  1. 使用已命名的名称空间中声明的变量代替全局变量
  2. 使用未命名的名称空间中声明的变量代替静态全局变量
  3. 将函数库类库放在一个名称空间中
  4. 少用using编译指令
  5. 避免在头文件中使用using编译指令。
  6. 导入名称时,首选using声明和作用域解析符
  7. 首选在局部使用using声明
4.一个例子
//名称空间6.h
#include
#include
using std::cin;
using std::cout;
using std::endl;
using std::string;
namespace pers{
    struct Person
    {
        string fname;
        string lname;
    };
    void getPerson(Person&);
    void showPerson(const Person&);
}
namespace debts{
    using namespace pers;
    struct Debt
    {
        Person name;
        double amount;
    };
    void getDebt(Debt &);
    void showDebt(const Debt &);
    double sumDebts(const Debt ar[],int n);
}
//名称空间6.cpp
#include"名称空间6.h"

namespace pers{
    void getPerson(Person &rp){
        cout<<"enter first name: ";
        cin>>rp.fname;
        cout<<"enter last name: ";
        cin>>rp.lname;
    }
    void showPerson(const Person& rp){
        cout<>rd.amount;
    }
    void showDebt(const Debt & rd){
        showPerson(rd.name);
        cout<<": $"< 
//名称空间6main.cpp
#include"名称空间6.h"
void other();
void another();
int main(){
    using debts::Debt;
    using debts::showDebt;
    Debt golf={{"Benny","Goatsniff"},120.0};
    showDebt(golf);
    other();
    another();
}
void other(){
    using namespace debts;
    Person dg={"Doodles","Glister"};
    showPerson(dg);
    cout< 
PS D:studyc++> g++ -I .path_to_c++include -o test .path_to_c++名称空间6main.cpp .path_to_c++名称空间6.cpp
PS D:studyc++> .test.exe
Benny Goatsniff: $120
Doodles Glister
enter first name: Ann   
enter last name: Cherry
enter debt: 200
enter first name: Ban 
enter last name: Tank
enter debt: 230
enter first name: Sam
enter last name: Captain
enter debt: 300
Ann Cherry: $200
Ban Tank: $230
Sam Captain: $300
Total debt: $730
Milo Rightshift
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026757.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号