Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';类中有一个非整型静态常量成员吗? 我注意到C++将不编译如下: class No_Good { static double const d = 1.0; };_C++ - Fatal编程技术网

为什么可以';类中有一个非整型静态常量成员吗? 我注意到C++将不编译如下: class No_Good { static double const d = 1.0; };

为什么可以';类中有一个非整型静态常量成员吗? 我注意到C++将不编译如下: class No_Good { static double const d = 1.0; };,c++,C++,但是,它允许将double更改为int、unsigned或任何整数类型: class Happy_Times { static unsigned const u = 1; }; 我的解决方案是将其改为: class Now_Good { static double d() { return 1.0; } }; 并认为编译器将足够智能,可以在必要时内联。。。但这让我很好奇 为什么C++设计器允许静态const一个int或un签署,而不是一个双?< /p> 编辑:我正在Windows X

但是,它允许将double更改为int、unsigned或任何整数类型:

class Happy_Times {
  static unsigned const u = 1;
};
我的解决方案是将其改为:

class Now_Good {
  static double d() { return 1.0; }
};
并认为编译器将足够智能,可以在必要时内联。。。但这让我很好奇

<>为什么C++设计器允许静态const一个int或un签署,而不是一个双?< /p> 编辑:我正在Windows XP上使用visual studio 7.1(.net 2003)

编辑2:

问题已经回答,但为了完成,我看到的错误是:

error C2864: 'd' : only const static integral data members can be initialized inside a class or struct

我不知道为什么它会处理与int不同的double。我以为我以前用过那种形式。以下是另一种解决方法:

class Now_Better
{
    static double const d;
};
在.cpp文件中:

double const Now_Better::d = 1.0;

问题是,对于整数,编译器通常不必为常量创建内存地址。它在运行时不存在,它的每次使用都会内联到周围的代码中。它仍然可以决定给它一个内存位置——如果它的地址曾经被占用(或者如果它通过const引用传递给函数),那么它必须这样做。为了给它一个地址,它需要在一些翻译单元中定义。在这种情况下,您需要将声明与定义分开,否则它将在多个翻译单元中定义

使用无优化(
-O0
)的g++时,它会自动内联常量整型变量,但不会内联常量双精度值。在更高的优化级别(例如,
-O1
)下,它将常量加倍内联。因此,以下代码在
-O1
处编译,而不是在
-O0
处编译:

// File a.h
class X
{
 public:
  static const double d = 1.0;
};

void foo(void);

// File a.cc
#include <stdio.h>

#include "a.h"

int main(void)
{
  foo();
  printf("%g\n", X::d);

  return 0;
}

// File b.cc
#include <stdio.h>

#include "a.h"

void foo(void)
{
  printf("foo: %g\n", X::d);
}

为了实现最大的可移植性,您应该在头文件中声明常量,并在某个源文件中定义它们一次。如果没有优化,这不会影响性能,因为您无论如何都没有进行优化,但是如果启用优化,这可能会影响性能,因为编译器无法再将这些常量内联到其他源文件中,除非启用“整个程序优化”。

我看不出技术原因

struct type {
    static const double value = 3.14;
};
这是禁止的。任何情况下,您发现它的工作原理都是由于非可移植的实现定义的特性。它们似乎也只有有限的用途。对于在类定义中初始化的整型常量,可以使用它们并将它们作为非类型参数传递给模板,还可以将它们用作数组维度的大小。但对于浮点常量不能这样做。允许浮点模板参数将带来它自己的一套规则,这并不值得费心

但是,下一个C++版本将允许使用<代码> CONTXPRP</代码>:

struct type {
    static constexpr double value = 3.14;
    static constexpr double value_as_function() { return 3.14; }
};
并将使
type::value
成为常量表达式。同时,您最好的选择是遵循
std::numeric\u limits

struct type {
    static double value() { return 3.14; }
};
它不会返回常量表达式(编译时不知道值),但这只关系到理论,因为实际值无论如何都会内联。见提案。它包含

4.4

浮点常量表达式

传统上,评估 温度下的浮点常数表达式 编译时间是一个棘手的问题。对于 我们建议统一性和普遍性 允许数据的常量表达式 浮点数类型,初始化为 任何浮点常数 表达。这也会增加 与C99的兼容性[ISO99,§6.6] 允许

[#5]计算结果为 常量在几个方面都是必需的 上下文。如果一个floating表达式是 在翻译环境中评估- 环境、算法精度和性能 范围应至少与 正在对表达进行评估 执行环境


<>这并没有给出一个理论,但这里是Stroustrup在C++编程语言第三版中所说的:

10.4.6.2构件常数

也可以初始化 静态积分常数构件法 添加常量表达式 其成员声明的初始值设定项。 例如:

class Curious {
    static const int c1 = 7;        // ok, but remember definition
    static int c2 = 11;             // error: not const
    const int c3 = 13;              // error: not static
    static const int c4 = f(17);    // error: in-class initializer not constant
    static const float c5 = 7.0;    // error: in-class not integral
    // ...
};
class X {
    enum { c1 = 7, c2 = 11, c3 = 13, c4 = 17 };
    // ...
};
但是,必须(唯一)定义已初始化的成员 在某个地方,初始值设定项可能不存在 请重复:

const int Curious::c1;  // necessary, but don't repeat initializer here
我认为这是个错误。当你需要一个符号常量时 在类声明中,使用 枚举器(4.8、14.4.6、15.3)。对于 例如:

class X {
    enum { c1 = 7, c2 = 11, c3 = 13, c4 = 17 };
    // ...
};
这样,其他地方就不需要成员定义,您也不需要 试图声明变量, 浮点数等

在第C.5节(常量表达式)的附录C(技术细节)中,Stroustrup对“常量表达式”有这样的说法:

在数组边界(5.2)、大小写标签(6.3.2)等位置, 枚举数(4.8)和C++的初始化器需要 恒定表达式。常量表达式的计算结果为 积分或枚举常数。这样的表达 由文字(4.3.1、4.4.1、4.5.1)组成, 枚举数(4.8)和由初始化的常量 常量表达式。在模板中,是一个整数模板 也可以使用参数(C.13.3)。浮动文字(4.5.1) 仅当显式转换为整数时才能使用 类型。函数、类对象、指针和引用 可以用作sizeof的操作数 仅限操作员(6.2)

直觉上,常量表达式是简单的表达式 可以在程序运行之前由编译器对其进行评估 已链接(9.1)并开始运行


请注意,他几乎忽略了浮点,因为他能够在“常量表达式”中使用。我怀疑浮点被排除在这些类型的常量表达式之外,仅仅是因为它们不够“简单”。

以下是我基于Stroustrup关于类内定义的声明的理解

类通常在头中声明