变量的多重定义问题是由于语言定义中的两个主要缺陷造成的。
如下所示,您可以轻松解决该问题。没有技术的之所以没有直接支持。这与该功能的需求不够高有关,委员会成员选择将其作为优先事项。
首先,为什么多重定义通常是一个问题。由于 C++ 缺乏对单独编译模块的支持(缺陷#1),程序员必须通过使用文本预处理等来模拟该功能。然后很容易不经意间引入两个或多个同名的定义,这很可能是错误的。
对于函数,这是通过以下方法解决的inline
关键字和属性。独立函数只能显式地inline
,而成员函数可以隐式地inline
通过在类定义中进行定义。不管怎样,如果一个函数是inline
那么它可以在多个翻译单元中定义,并且必须在使用它的每个翻译单元中定义,并且这些定义必须是等效的。
主要是该解决方案允许在头文件中定义类。
不需要这样的语言功能来支持头文件中定义的数据、变量,因此它不存在:您不能拥有inline
变量。这是语言缺陷#2。
但是,您可以获得effect of inline
通过特殊豁免的变量static
类模板的数据成员。豁免的原因是类模板通常必须在头文件中完全定义(除非模板仅在翻译单元内部使用),因此类模板能够具有static
数据成员,有必要获得一般规则的豁免或一些特殊支持。委员会选择了豁免规则途径。
template< class Dummy >
struct math_
{
static double const pi;
};
template< class Dummy >
double const math_<Dummy>::pi = 3.14;
typedef math_<void> math;
上述内容被称为模板化常量技巧。据我所知,我是在 [comp.lang.c++] Usenet 组中曾经介绍过它的人,所以我不能将其归功于其他人。我也在 SO 上发布过几次。
无论如何,这意味着每个 C++ 编译器和链接器内部支持并且必须支持所需的机制inline
数据,但该语言不具备该功能。
然而,第三方面,C++11constexpr
,你可以将上面的内容写成
struct math
{
static double constexpr pi = 3.14;
};
嗯,有一个区别,你不能获取 C++11 的地址math::pi
,但这是一个非常小的限制。