声明普通类和类模板的静态数据成员

2024-04-12

我读到在源文件中定义静态数据成员的原因是因为如果它们位于头文件中并且多个源文件包含头文件 - 定义将多次输出。我可以理解为什么这对于静态常量数据成员来说是一个问题,但是为什么这对于静态数据成员来说是一个问题呢?

我不太确定我完全理解如果定义写在头文件中为什么会出现问题......


变量的多重定义问题是由于语言定义中的两个主要缺陷造成的。

如下所示,您可以轻松解决该问题。没有技术的之所以没有直接支持。这与该功能的需求不够高有关,委员会成员选择将其作为优先事项。

首先,为什么多重定义通常是一个问题。由于 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,但这是一个非常小的限制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

声明普通类和类模板的静态数据成员 的相关文章

  • 更改 WinForms 按钮突出显示颜色

    I found 这一页 https stackoverflow com questions 9260303 how to change menu hover color winforms 其中概述了如何更改 MenuStrip 及其项目的呈
  • C# 中的密码恢复工具不起作用

    嗨 我对此还很陌生 我创建了一个门户 用户可以登录并在其中查看我制作的其他程序 问题是密码恢复似乎不起作用 我没有收到任何错误消息 我只是收到消息 我们无法访问您的信息 请重试 我已经正确设置了 ASP NET 配置 并使用不同的用户和权限
  • 为什么仍然需要在 using 语句的 RHS 中使用 typename 来消除依赖类型的歧义?

    我很清楚为什么需要使用typename对于依赖类型 因为编译器在看到类似的内容时可能无法消除类型和变量声明之间的歧义T type 参见例如这个答案 https stackoverflow com a 613132 3093378一个很好的解
  • 如何从头开始重复C程序并清理屏幕和第一个输入值?

    我是编程新手 我写了一个简单的程序 我想一次又一次地重复该程序 并且只有当用户想要退出时它才能退出 这是我的程序 include
  • 验证码怎么写?

    我正在开发一个注册表 我想放置验证码 我生成一个随机字符串 但如何将其转换为图像 否则我如何开发验证码或任何参考 谢谢 Try out 验证码 http recaptcha net plugins aspnet 或查看博客文章 使用 Asp
  • DPI 图形屏幕分辨率像素 WinForm PrintPageEventArgs

    对于运行我的应用程序的任何显示器 Dpi 点与像素有何关系 int points Screen primary public Form1 InitializeComponent points 1 primary null void OnPa
  • 字符串中unicode字符的正则表达式

    我正在使用 C 进行一些 OCR 工作 并提取了我需要使用的文本 现在我需要使用正则表达式解析一行 string checkNum string routingNum string accountNum Regex regEx new Re
  • Collection.Contains() 使用什么来检查现有对象?

    我有一个强类型的自定义对象列表 MyObject 它有一个属性Id 以及一些其他属性 假设Id of a MyObject将其定义为唯一 我想检查我的收藏是否还没有MyObject对象有一个Id在我添加新的之前 共 1 个MyObject到
  • C 中经过的时间

    include
  • 无法将方法组分配给 asp.net、linq、c# 中的隐式类型局部变量

    public void selectqueryasso CustomerOrderResult cso new CustomerOrderResult var a from as1 in ds orders from as2 in ds o
  • 慢速 WPF 文本框

    我正在开发一个简单的串行数据查看器 它将用于观察传输到计算机串行端口之一的数据 我使用 C 和 WPF 编写了一个测试应用程序 它只是将最近读取的行放入文本块中 但是 它会跳过所有其他行 我的理论是 在 WPF 渲染窗口之前 新数据会被放入
  • 在 C 中使用另一个结构中的二维结构数组的编码问题

    我正在使用一个二维结构数组 它是另一个结构的一部分 这不是我做过很多事的事情 所以我遇到了问题 该函数在接近末尾的 测试 for 循环后最终失败 它在出现段错误之前正确打印出一行 我的代码中将数据读入虚拟二维结构数组的部分工作得很好 所以它
  • 最好的 C++ 编译器是哪个? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 最佳实践:从属性中抛出异常

    什么时候适合从属性 getter 或 setter 中抛出异常 什么时候不合适呢 为什么 关于这个主题的外部文档的链接会很有帮助 谷歌搜索结果出奇的少 Microsoft 在以下位置提供了有关如何设计属性的建议 http msdn micr
  • 同时重新排序和旋转图像的高效方法

    为了快速加载 jpeg 我为turbojpeg 实现了一个 mex wrapper 以有效地将 大 jpeg 读入 MATLAB 对于 4000x3000px 的图像 实际解码只需要大约 120 毫秒 而不是 5 毫秒 然而 像素顺序是 R
  • 在源代码和预编译二进制文件之间切换

    我们的应用程序中有大量的库 库是用 C 或 C 编写的 平台 net Framework Windows 64 位 将所有内容编译为源代码需要花费大量时间 我们正在考虑切换到预构建的二进制文件 但我们仍然希望保留返回源代码的可能性 作为版本
  • 如何将 MouseDown 事件放入样式中?

    这有效 XAML
  • 如何在 MVC 5 中设置自定义 ClaimsPrincipal?

    我创建了一个自定义主体类 public class FacebookPrincipal ClaimsPrincipal public JObject Data get set 我想用它 当用户登录时 我尝试设置 var fbP new Fa
  • Bazel:为 cc_binary/cc_test 设置运行时环境变量和配置文件位置

    我正在尝试在 Linux 上的 C 应用程序中使用 odbc 以下构建文件用于将库作为外部依赖项包含在内 licenses notice cc library name lib srcs lib libodbc so lib64 libod
  • scanf() 不等待用户输入[重复]

    这个问题在这里已经有答案了 我正在使用 c 中的双向链表来制作树 我在该函数中使用递归调用 但不知何故它不起作用 我的代码是 struct node int data struct node right struct node left s

随机推荐