c – 具有私有构造函数和自身静态数组的类

前端之家收集整理的这篇文章主要介绍了c – 具有私有构造函数和自身静态数组的类前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
对不起,如果标题令人困惑,我找不到一个简单的方法来写一个简单的句子.无论如何,我面临的问题是:
// 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 :: array,除非我在类中添加一个公共ctor SomeThing().它适用于旧式数组,我可以定义数组,并在SomeThing :: generateLookupTables()函数中填充它.显然类型为std :: array< SomeThing,64>没有构造函数.关于如何使其工作的任何想法,或者对于这个概念可能是更好的结构?

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

朋友std :: array< SomeThing,64>方法似乎是个好主意,但是:

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

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

解决方法

解决方案:
std::array<SomeThing,64> SomeThing::lookup_table_0 {{ }};

注意:正如here所解释的那样,{{}}需要在gcc中对std :: array进行值初始化而不发出警告. = {}和{}是正确的,但gcc仍然会发出警告.

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

首先进行术语检查:所有对象都在C中初始化.有三种形式,默认值,值和零.没有“未初始化”的对象;没有显式初始化程序的对象称为默认初始化.在某些情况下,这意味着对象的成员变量可能是不确定的(“垃圾”).

no-initializer版本有什么问题?首先,std :: array< SomeThing,64>的构造函数.被定义为删除,因为声明std :: array< SomeThing,64> X;将是不正确的(由于缺少SomeThing的可访问的默认构造函数,当然).

这意味着任何尝试使用std :: array< SomeThing,64>的默认构造函数代码.反过来又形成了不良形象.定义:

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

确实尝试使用默认构造函数,因此它是错误的.但是一旦你开始介绍初始化器,那么std :: array的默认构造函数就不再存在了;由于std :: array是一个聚合,因此聚合初始化会绕过隐式生成的构造函数. (如果有任何用户声明的构造函数,那么它将不再是聚合).

带有初始化程序的版本因[dcl.init] / 13(n3936)而起作用:

An initializer for a static member is in the scope of the member’s class

列表初始化的定义在此处将{}转换为{SomeThing()}.

猜你在找的C&C++相关文章