8

对不起,如果标题令人困惑,我找不到一个简单的方法来用一个简单的句子来写它。无论如何,我面临的问题:

 // header:
class SomeThing
{
 private:
   SomeThing() {} // <- so users of this class can't come up
                  //    with non-initialized instances, but
                  //    but the implementation can.

   int some_data; // <- a few bytes of memory, the default
                  //    constructor SomeThing() doesn't initialize it
 public:
   SomeThing(blablabla ctor arguments);

   static SomeThing getThatThing(blablabla arguments);

   static void generateLookupTables();
 private:

   // declarations of lookup tables
   static std::array<SomeThing, 64> lookup_table_0;
   static SomeThing lookup_table_1[64];
};

getThatThing函数旨在从查找表中返回一个实例。

 // in the implementation file - definitions of lookup tables

 std::array<SomeThing, 64> SomeThing::lookup_table_0; // error

 SomeThing Something::lookup_table_1[64]; // <- works fine

我不能使用std::arrayof Something,除非我在课堂上添加一个公共 ctor SomeThing()。它适用于旧式数组,我可以定义数组,并在SomeThing::generateLookupTables()函数中填充它。显然该类型std::array<SomeThing, 64>没有构造函数。关于如何使其工作的任何想法,或者这个概念的更好结构?

============= 编辑 =======

这种friend std::array<SomeThing, 64>方法似乎是个好主意,但是:

它也将用于其他地方的数组中。我想保证这个类总是对外部用户保持某些不变量。使用这个友好的数组,用户可能会意外地创建一个未初始化的SomeThing.

此外,查找表是使用相当复杂的过程生成的,不能按内联方式完成,如std::array<SomeThing, 64> SomeThing::lookup_table_0(some value)

4

3 回答 3

5

该类在尝试定义实例时std::array<SomeThing, 64>显然无权访问默认构造函数。private您可以通过添加给它必要的访问权限

friend class std::array<SomeThing, 64>;

的定义SomeThing

于 2014-12-30T00:51:55.547 回答
4

解决方案:

std::array<SomeThing, 64> SomeThing::lookup_table_0 {{ }};

注意:正如这里所解释的, 需要在 gcc 中对没有警告的{{}}值进行值初始化。并且是正确的,但 gcc 还是会发出警告。 std::array= {}{}

解决方案的关键是必须存在某种形式的初始化程序。


首先进行术语检查:所有对象都在 C++ 中初始化。this 有三种形式,defaultvaluezero。没有“未初始化”的对象;没有显式初始化器的对象称为default-initialized。在某些情况下,这意味着对象的成员变量可能是不确定的(“垃圾”)。

无初始化器版本有什么问题?首先,构造函数 forstd::array<SomeThing, 64>定义为已删除,因为声明std::array<SomeThing, 64> x;格式不正确(当然,由于缺少可访问的默认构造函数 for SomeThing)。

这意味着任何尝试使用默认构造函数的代码std::array<SomeThing, 64>都是格式错误的。定义:

std::array<SomeThing, 64> SomeThing::lookup_table_0;

确实尝试使用默认构造函数,因此它格式错误。然而,一旦你开始引入初始化器,那么默认的构造函数std::array就不再起作用了;因为std::array是一个聚合然后聚合初始化发生,它绕过隐式生成的构造函数。(如果有任何用户声明的构造函数,那么它将不再是一个聚合)。

由于 [dcl.init]/13 (n3936),带有初始化程序的版本可以工作:

静态成员的初始化程序在成员类的范围内

列表初始化的定义转换{ }{ SomeThing() }这里。

于 2014-12-30T01:44:34.623 回答
4

由于您的构造函数是私有的,std::array因此不能使用它。

您可以添加friend class std::array<SomeThing, 64>;SomeThing授予对构造函数的访问权限。

另一种方法是使用可用的公共构造函数来初始化数组的元素:

std::array<SomeThing, 64> SomeThing::lookup_table_0{
    SomeThing(blablabla_ctor_arguments), ..
};

编辑:

如果您有可用的移动或复制构造函数,您甚至可以这样做:

std::array<SomeThing, 64> SomeThing::lookup_table_0{ SomeThing() };

让你的整个数组默认初始化。

于 2014-12-30T00:50:58.790 回答