extern如何在名称空间中工作?

时间:2015-05-28 21:39:49

标签: c++ namespaces global-variables const extern

我正在运行一个类似于我发现here的简单程序。当在多个文件中包含常量时,它意味着减少代码膨胀。它通过在命名空间中使用const全局变量及其各自的extern前向声明来实现此目的。

globals.h

#ifndef GLOBALS_H_
#define GLOBALS_H_

namespace Constants
{
    // forward declarations only
    extern const double pi;
    extern const double avogadro;
    extern const double my_gravity;
}

#endif

globals.cpp

namespace Constants
{
    // actual global variables
    extern const double pi(3.14159);
    extern const double avogadro(6.0221413e23);
    extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
}

source.cpp

#include <iostream>
#include <limits>

#include "globals.h"

int main()
{
    double value_of_pi = Constants::pi;

    std::cout << value_of_pi;

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

我假设Constants :: pi获取globals.cpp Constants命名空间中包含的值pi,并且能够这样做,因为它可以从包含的globals.h访问命名空间本身。我不明白为什么globals.cpp中的 const全局定义/初始化 需要extern关键字?我尝试删除globals.cpp中的extern个关键字,认为它不是必需的,但我的程序在没有它们的情况下不会运行。我以为extern仅用于前言声明?为什么 const全局定义/初始化 需要它们?它与它们定义的命名空间有关吗?

1 个答案:

答案 0 :(得分:10)

  

在多个文件中包含常量时,它意味着减少代码膨胀

我建议不要专注于这种优化,除非它变得非常必要,而是选择最简单的设计:直接在头文件中定义这些常量并包含来自所有翻译单元的头文件(&#34;。 cpp文件&#34;)需要访问这些常量。由于这些对象是const,因此它们将具有内部链接,并且链接器不会因违反单一定义规则而尖叫。

  

我尝试删除globals.cpp中的extern关键字,认为它不是必需的,但我的程序在没有它们的情况下运行

这是因为具有静态存储持续时间的命名空间范围const对象(如pi变量)具有内部链接,除非您明确将它们定义为{{ 1}}。

  

我认为extern仅用于前言声明?

extern用于声明在另一个翻译单元中定义的变量(&#34; .cpp文件&#34;)。如果对象为extern,则定义它的翻译单元需要将其明确标记为const,以使其具有外部链接并且可以从其他翻译单元中看到(这不会是如果对象不是extern)则必需。

  

它与定义它们的命名空间有关吗?

不,这是具有静态存储持续时间的所有命名空间级别const对象的规则,并且在C ++标准的[basic.link] / 3段中指定:

  

具有命名空间范围(3.3.6)的名称具有内部链接(如果它是

的名称)      

(3.1)[...] - 显式的变量,函数或函数模板   声明静态;或者,

     

(3.2) - 非易失性const限定类型的变量,既未明确声明为extern,也未声明为具有外部链接;或

     

(3.3) - 匿名工会的数据成员。