C++命名空间namespace

前面文章所写的代码都是单一个文件就把功能实现完了,但是大多数场合我们都需要多个文件来合作执行,每个文件针对相应的需求完成特定的功能。因此我们的代码会越写越多,功能文件也会越来越多,工程一旦大起来就需要多位开发人员一起来完成一个这个工程。我们没办法保证每位开发人员所使用的标识符命名不产生冲突,所以标准的C++引入了关键字namespace(命名空间/名字空间/名称空间/名域),可以更好地控制标识符的作用域,避免冲突。下面我们使用一个工程代码来了解下具体namesapce的作用及使用方法。


前面由于功能较少我们把类的定义和实现都放在了一个文件里面,但一般情况下,我们会使用一个 .h 文件来定义,而实现我们放在 .cpp 文件里面,使用声明的话中间需要使用 include 把 .h 包含进来。在上一章代码的基础上添加一个 Dog 类,将Dog 和 Person 这两个类的定义分别放到两个 .h 里面,实现放在各自对应的 cpp 文件里面。将 main 函数单独放一个 cpp 文件。

下面我们先看一下 Dog 这个类的定义,如下:

class Dog{
    private:
        char *name;
        int age;
    public:
        void setName(char *name);
        int setAge(int age);
        void printInfo(void);
};

上面的定义跟 Person 类差不多,现在我们引入一个问题,假设 Person 类和 Dog 类有一个同名的方法,如 void printVersion(void) 这个函数,那我们在 main 函数里面调用这个函数的时候如何区分调用的是 Person 类的还是 Dog 类的呢?下面这样显然是不行的:

    printVersion();
    printVersion();

因此这里我们引入一个 namespace 的概念,用来区分这两个函数分别指向谁的,修改后的 Dog 类和 Person 类后如下:

namespace C{
    class Dog{
        private:
            char *name;
            int age;
        public:
            void setName(char *name);
            int setAge(int age);
            void printInfo(void);
    };

    /* 使用相同的函数名,引入命名空间 */
    void printVersion(void);    
}
namespace A{
    ....
    ....
    void printVersion(void);
}

这样就给这个类定义了一段空间,它们分别属于 A 和 C,之后我们调用里面的函数就可以这样:

A::printVersion();
C::printVersion();

另外我们在调用那些类的时候也不能单纯的直接使用类名来定义了,需要在前面声明他属于哪个 namesapce的,如下:

A::Person per;
C::Dog dog;

但是实际上他们类名都不是一致的,我们每次定义都要在前面加上 A:: 这样的字眼显示太麻烦了,于是我们这里引入一个 using,只需要在文件前面声明一下后面即可直接使用 Person 来定义类变量了,如下:

using A::Person; /* 以后直接调用Person即表示a::Person */
using C::Dog;

当然还有一种方式,如下:

using namespace A; /* 把A对应的类和函数都导进来,效果跟上面一样 */
using namespace C;

下面看下修改后的 main.cpp,代码都备注好了,也做了总结:

#include <stdio.h>
#include "person.h"/* 导入 .h 文件 */
#include "dog.h"

/*****************************************************
1. 直接使用
a::func,a::fun2

2. using声明
using a::fun;  //以后直接调用fun即表示a::fun

3.using编译
using namespace a; //以后调用fun,fun2即可 
*****************************************************/

/* global namespace(全局命名空间) */
/* 每次都加个C::太麻烦,可以使用using */
/* 把A::Person放入global namespace, 以后可以使用Person来表示A::Person */
using namespace A;/* 把A对应的类和函数都导进来 */

/* 把C::Dog放入global namespace, 以后可以使用Dog来表示C::Dog */
using namespace C;

int main(int argc, char **argv)
{   
    /* local namespace(局部命名空间) */

    /* per称为Person这个类的对象 */
    //A::Person per;
    Person per;
    per.setName("Zhangsan");
    per.setAge(200);/* 形参为200则输入不在范围内,类里面加了限制会返回-1 */
    per.setWork("doctor");
    per.printInfo();

    Dog dog;
    dog.setName("wangcai");
    dog.setAge(1);
    dog.printInfo();

    A::printVersion();
    C::printVersion();

    return 0;
}

dog.cpp

#include <iostream>/* 使用cout需要加上头文件 */ 
#include "dog.h"

/* 声明名字空间,大括号内属于C的空间段 */
namespace C{

    /* 声明std,否则下面的 cout 需要写成 std::cout */
    using namespace std;

    /* 实现person类里面的这个函数 */
    void Dog::setName(char *name)
    {
        /* 加上this可以表明是当前类里面参数  */
        this->name = name;
    }

    int Dog::setAge(int age)
    {
        /* 加以限制,避免出错设置,把年龄限制在0-20 */
        if(age<0 || age>20)
        {
            this->age = 0;
            return -1;
        }
        this->age = age;
        return 0;
    }

    void Dog::printInfo(void)
    {
        //printf("name = %s, age = %d\n", name, age);
        /* C++里面我们一般使用cout来做为输出显示,endl为换行 */ 
        cout<<"name = "<<name<<" age = "<<age<<endl; 
    }

    void printVersion(void)
    {
        //printf("Dog v1, by zephyr\n");
        /* C++里面我们一般使用cout来做为输出显示,endl为换行 */ 
        cout<<"Dog v1, by zephyr"<<endl;
    }
}

dog.h

namespace C{
    class Dog{
        private:
            char *name;
            int age;
        public:
            void setName(char *name);
            int setAge(int age);
            void printInfo(void);
    };

    /* 如果使用相同的函数名,则需引入命名空间 */
    void printVersion(void);    
}

person.cpp

#include <iostream>
#include "person.h"

namespace A{

    /* 实现person类里面的这个函数 */
    void Person::setName(char *name)
    {
        /* 加上this可以表明是当前类里面参数  */
        this->name = name;
    }

    int Person::setAge(int age)
    {
        /* 加以限制,避免出错设置,把年龄限制在0-150 */
        if(age<0 || age>150)
        {
            this->age = 0;
            return -1;
        }
        this->age = age;
        return 0;
    }

    void Person::setWork(char *work)
    {
        /* 加上this可以表明是当前类里面参数  */
        this->work = work;
    }

    void Person::printInfo(void)
    {
        std::cout<<"name = "<<name<<" age = "<<age<<" work = "<<work<<std::endl;
    }

    void printVersion(void)
    {
        std::cout << "Person v1, by zephyr" << std::endl;
    }
}

person.h

#include <stdio.h>

namespace A{
    class Person{

    /* 私有成员 */
    private:
    /* 为什么要把它们设置为私有呢?是为了避免用户随意修改或设置错误的值,可以在public的方法中加以限制 */
        char *name;
        int age;
        char *work;

    /* 公开成员 */  
    public: 
        /* 这些公开的方法可以用于设置该类中的私有变量,提供一个修改窗口给用户,用户不能直接访问上面的私有成员 */
        void setName(char *name);

        int setAge(int age);

        void setWork(char *work);

        void printInfo(void);
    };

    void printVersion(void);
}

代码非常简单,就是简单的打印一些信息,我是在 linux 的平台下进行编译的,所以使用的编译器是 g++,对应的 makefile 如下:

person: main.o person.o dog.o
    g++ -o $@ $^

%.o : %.cpp
    g++ -c -o $@ $<

clean:
    rm -f *.o person

以上一些语法的含义如下:

/* person依赖于main.o和person.o */
/* $@:表示目标 */
/* $^:表示全部依赖 */
/* $<:表示第一个依赖 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值