在C++ 11之前,我们只能对整数或枚举类型的静态const成员执行类内初始化.Stroustrup在他的C++ FAQ中讨论了这个问题,给出了以下示例:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
Run Code Online (Sandbox Code Playgroud)
以下推理:
那么为什么存在这些不方便的限制呢?类通常在头文件中声明,并且头文件通常包含在许多翻译单元中.但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏.
但是,C++ 11放宽了这些限制,允许非静态成员的类内初始化(§12.6.2/ 8):
在非委托构造函数中,如果给定的非静态数据成员或基类未由mem-initializer-id指定(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer)然后,实体不是抽象类(10.4)的虚基类
- 如果实体是具有大括号或等于初始值的非静态数据成员,则按照8.5中的规定初始化该实体;
- 否则,如果实体是变体成员(9.5),则不执行初始化;
- 否则,实体默认初始化(8.5).
第9.4.2节还允许非const静态成员的类内初始化,如果它们用说明constexpr符标记的话.
那么我们在C++ 03中受到限制的原因究竟发生了什么?我们只是简单地接受"复杂的链接器规则"或者是否有其他改变使得这更容易实现?
我有一个没有构造函数的抽象C++类.它应该是一个基类,所以其他类可以继承它.我想要做的是在基类中声明一个常量变量,并在每个派生类的构造函数中初始化它,但在每个类中没有其他地方.它在C++中是否合法?如果是这样,我该怎么做?
我从RFC 246中知道这一点:
- 常量声明常量值.它们代表一个值,而不是内存地址.这是人们可以达到的最常见的事情,并且
static几乎在所有情况下我们今天都会知道它.- 静态声明全局变量.这些代表一个内存地址.它们很少使用:主要用例是全局锁,全局原子计数器以及与传统C库的接口.
当我试图维护一张桌子时,我不知道两者之间究竟有什么不同.
我应该选择哪一个?
我在Ah中有以下代码:
class A
{
public:
...
private:
...
const int X = 1;
float Y[X];
...
};
Run Code Online (Sandbox Code Playgroud)
如果项目中只包含标题Ah,则编译很好.但是,如果我包括啊,让我们说A.cpp它会给我带来如下奇怪的错误:
...警告:非静态数据成员初始化程序仅适用于-std = c ++ 11或-std = gnu ++ 11 [默认启用]
...错误:无效使用非静态数据成员'A :: X'
......错误:从这个位置
即使我改变了const int X = 1;(虽然我需要它作为常量参数),但没有任何改变.
ps如果有意义我使用的是Qt 5.1
pss实际上使它static修复了错误.但为什么我必须这样做?
我有一段时间没有做过C++编码,我的朋友在做作业时遇到了麻烦.我从来没有真正合作过const,而且这使得这成为一场噩梦,因为我无法弄清楚构造函数的正确语法.想象一下,我有这个dvd.h:
class DVD {
const string title;
int minutes;
double price;
public:
DVD(const string t, int m, double p);
}
Run Code Online (Sandbox Code Playgroud)
3个私有成员变量,string是const.构造函数也需要一个const string.
所以现在,dvd.cpp我可以做以下事情:
#include "dvd.h"
DVD::DVD(const string t, int m, double p) {
const string title = t;
minutes = m;
price = p;
}
Run Code Online (Sandbox Code Playgroud)
一切都在世界上很好.然而,当我修改minutes的dvd.h是const(这是他的教授是如何构造的文件),我们有这样的dvd.h:
class DVD {
const string title;
const int minutes; // Here is the change …Run Code Online (Sandbox Code Playgroud) 为什么我不能在C++中这样做?
struct SomeStruct
{
public:
SomeStruct(const int someInt)
{
m_someInt = someInt;
}
private:
const int m_someInt;
};
Run Code Online (Sandbox Code Playgroud)
私有字段应该是常规整数吗?
我正在尝试创建一个结构(或类,无关紧要),其构造函数将值分配给结构的常量参数。即我不想在创建 Point 对象后更改它的任何变量。
以下代码显然不起作用,因为构造函数试图更改常量的值。
struct point
{
const int x;
const int y;
point(int _x = 0, int _y = 0)
{
x = _x;
y = _y;
}
};
point myPoint = point(5, 10);
std::cout << myPoint.x << myPoint.y << std::endl;
Run Code Online (Sandbox Code Playgroud) 那么这个问题可能与这些问题有相当多的重叠:
如何在类中初始化const成员变量
C++11中
的const成员变量在对象构造后初始化const成员变量
然而,这些都不能回答我最初的问题。主要区别在于我不想使用设置值而是使用构造函数参数进行初始化。
我想做的是这样的——
class myRectangle {
private:
const int length; //const mainly for "read-only" like
const int breadth; //protection
public:
myRectangle(int init_length, int init_breadth);
int calcArea(void);
void turn90Degrees(void);
/* and so on*/
Run Code Online (Sandbox Code Playgroud)
}
其中长度和宽度都是只读的,在构造后不会改变它们。
但当然,我的编译器不会允许我将它们设置在构造函数中,因为它们实际上是const的......
我没有拿出解决办法只是让他们变和只实现getter方法,使他们不能有效地改变,但我几乎感觉我在这里错过了明显的解决方案。
另外我觉得我在某种程度上误解了 const 的使用。那么,从那时起不更改数据是否“已经”成为编译时合同?因为在我的理解中,不知道常量在程序执行过程中占用的大小是否足够信息?
顺便说一句,使恒定静态的解决方案不适合我,因为我生成的每个矩形都应该有不同的大小。
感谢您的回答和澄清!
解决方案:初始化列表/委托构造函数