如何定义作为非实例化 class 的静态成员的数组的大小?

How to define the size of an array that is a static member of a non instanciable class?

我正在写一个 class 我不想实例化。它的所有成员都是静态的。这个class代表一个微控制器的外设。由于微控制器中只有一个外围设备的实例,因此创建该 class 的实例对我来说没有意义。 class只对那个外设的数据和功能进行了分组。

class 的其中一个数据成员是一个数组,class 的用户应在编译时定义其大小。如果我可以创建此 class 的对象,我知道我可以在构造函数的初始化列表中初始化常量,但我真的不想创建此 class 的实例。也许我可以使用模板并将数组大小设置为模板参数,但我需要为每个成员调用使用 my_class<5>::do_something() 之类的东西。有没有更简单的方法来解决这个问题?我想让我的 class 像这样:

class my_class
{
private:
    static const int _size;
    static int _array[_size];
public:
    static void array_size(int size) { _size = size; }
    static void do_something() { /* .... */ } 
};

您的主要要求是在编译时设置数组大小。这更像 C 风格,在编写 C++ 时通常会避免这种情况,但在您的情况下,使用宏可能更有意义,例如

#define ARRAY_SIZE 
... somewhere in your class ...
static int array_name[ARRAY_SIZE];

你最好的选择可能是一个很好的旧定义。

以下是我的结构(使用名称空间,因为它是执行仅静态 类 的惯用方法):

peripheral.h:

namespace peripheral {
  void do_something();
}

peripheral.cpp:

#ifndef PERIPH_ARRAY_SIZE
#  error "please define the size of array"
#endif

namespace {
  int _array[PERIPH_ARRAY_SIZE];
}

namespace peripheral {
  void do_something() {...}
}

允许用户设置大小的一种方法是将数组更改为向量。由于它是私有的,因此您可以控制它的使用方式。一个简单的 bool 将限制它是否调整大小一次并确保它确实调整大小:

class my_class
{
private:
    static const int _size = 10;
    static vector<int> _array;
    static bool arraySized;
public:
    static void array_size( int size = _size ) 
    {
        if ( !arraySized )
        {
            _array = vector<int>( size );
            arraySized = true;
        }
    }
    static void do_something() 
    {
        if ( arraySized )
        {
            /* .... */
        }
    }
};

虽然不是在编译时,但确实有同样的效果。

还有一些其他事情需要考虑,使用基于模板的方法可以允许创建 class 的多个实例。这可以打破你似乎想要的奇点原则

using my_class = my_class_impl<10>;

using my_class2 = my_class_impl<20>;
int main() {
    my_class::do_something();
    my_class2::do_something();
}

另一件事是最新的 Atmel 框架确实包含 headers 向量。您引用的信息一定是过时的。

考虑使用 class 参数化为 constexpr 数组大小的模板,然后创建一个别名:

#include <array>

template <std::size_t Size>
class my_class_impl {
private:
    static constexpr std::size_t size = Size;
    static std::array<int, Size> arr;
public:
    static void do_something() { /* .... */ }
};

template <std::size_t Size>
std::array<int, Size> my_class_impl<Size>::arr;

using my_class = my_class_impl<10>;

int main() {
    my_class::do_something();
}