C++命名空间namespace

来源:互联网 发布:windows中安装ipython 编辑:程序博客网 时间:2024/06/10 11:49

前面文章所写的代码都是单一个文件就把功能实现完了,但是大多数场合我们都需要多个文件来合作执行,每个文件针对相应的需求完成特定的功能。因此我们的代码会越写越多,功能文件也会越来越多,工程一旦大起来就需要多位开发人员一起来完成一个这个工程。我们没办法保证每位开发人员所使用的标识符命名不产生冲突,所以标准的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::fun22. using声明using a::fun;  //以后直接调用fun即表示a::fun3.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 *//* $@:表示目标 *//* $^:表示全部依赖 *//* $<:表示第一个依赖 */