2017-01-01 9 views
1

Я пишу класс, который я не хочу создавать. Все его члены статичны. Этот класс представляет собой периферию микроконтроллера. Поскольку в микроконтроллере только один экземпляр этого периферийного устройства не имеет смысла, я создаю экземпляры этого класса. Класс группирует только данные и функции этого периферийного устройства.Как определить размер массива, который является статическим членом не подкрепляемого класса?

Одним из членов данных класса является массив, размер которого пользователь класса должен определять во время компиляции. Если бы я мог создавать объекты этого класса, я знаю, что могу инициализировать 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() { /* .... */ } 
}; 
+2

Если размер устанавливается во время компиляции то, что является 'статической силы ARRAY_SIZE (интермедиат размер) {_size = размер; } 'должен делать? – wally

+0

Рассмотрим одноэлементный класс. Он имеет некоторые преимущества перед старыми статическими данными. –

+0

@ n.m., Можете ли вы сказать больше о? – rrd

ответ

3

Рассмотрите возможность использования шаблона класса параметризованное с 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

Главное ваше требование состоит в том, чтобы размер массива был установлен во время компиляции. Это более C-иш, что-то вы бы вообще избегать при написании C++, но в вашем случае, это могло бы иметь больше смысла использовать макросы, такие, как

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

На самом деле я использую макросы прямо сейчас, но этот класс будет частью библиотеки. Я хочу разрешить пользователю определять размер массива в коде вместо использования флага -DARRAY_SIZE во время компиляции. – rrd

+0

Просто уточнить: когда вы говорите «часть библиотеки», вы имеете в виду, что пользователь должен статически связать указанную библиотеку с их кодом? – mgarey

+0

Если это так, рассмотрите n.m.комментарий в вашем вопросе (используя класс Singleton, а не статические члены) – mgarey

2

Ваш лучший выбор, вероятно, хороший старый определить.

Вот как я бы структурировать это (с помощью пространств имен, так как это идиоматический способ сделать статическое электричество только классы):

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

Одним из способов, позволяющих пользователю установить размер, было бы изменение массива на вектор. Поскольку он является частным, вы контролируете, как он используется. Простой 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) 
     { 
      /* .... */ 
     } 
    } 
}; 

Пока не время компиляции, он имеет тот же эффект.

Несколько других вещей, о которых стоит подумать, используя подход, основанный на шаблонах, может создавать более одного экземпляра этого класса. Что может нарушить принцип особенность, что вы, кажется, хотите

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 действительно включает заголовки для векторов. Информация, на которую вы ссылались, должна быть устаревшей.

+0

Спасибо, но у меня нет библиотеки std C++, это платформа I Я работаю. – rrd

+0

Если у вас нет библиотеки std C++, какую библиотеку вы используете? – tinstaafl

+0

Я программирую микроконтроллер Atmel AVR. Для этой платформы нет официальной библиотеки C++. – rrd