如何定义作为非instanciable类的静态成员的数组的大小?

时间:2017-01-01 16:49:27

标签: c++ arrays c++11 static compile-time-constant

我正在写一个我不想实例化的课程。它的所有成员都是静态的。该类代表微控制器的外围设备。由于微控制器中只有一个外设实例,因此我无法创建该类的实例。该类仅对该外设的数据和功能进行分组。

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

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() { /* .... */ } 
};

4 个答案:

答案 0 :(得分:2)

考虑使用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();
}

答案 1 :(得分:1)

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

以下是我如何构建它(使用命名空间,因为它是执行静态类的惯用方法):

为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() {...}
}

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

允许用户设置大小的一种方法是将数组更改为向量。由于它是私人的,你可以控制它的使用方式。一个简单的布尔将限制它是否大小一次并确保它的大小:

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 )
        {
            /* .... */
        }
    }
};

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

使用基于模板的方法要考虑的其他几个方面可以允许创建该类的多个实例。这可以打破你似乎想要的奇点原则

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框架确实包含了向量的标题。您引用的信息必须已过期。