Как правило, спорный дизайн класса имеет класс C++, содержащий указатель на «внешние данные». Часто лучший способ сделать это состоит в том, чтобы ваш C++ использовал копию внешних данных, поэтому ясно, что память де-распределена при уничтожении экземпляра класса.
Кроме того, как упоминалось выше, некоторые из этих вещей намного легче сделать с C++ 11. Если вы используете g++
или clang++
в качестве своего компилятора, возможно, у вас уже есть поддержка C++ 11, что делает многое очень приятным и легким, особенно для работы встраиваемых систем.
В данном конкретном случае, это полная и компилируемая программа (я использовал g++
и скомпилировал с g++ -std=c++11 -o relay relay.cpp
со следующим содержанием relay.cpp
.Я объединил все в один файл для простоты иллюстрации, но в реальной жизни вы должны сохранить разделение .cpp
и .h
файлов, которые у вас уже есть.
#include #include
class Relay
{
public:
Relay(std::vector<short> pins)
: _relay(pins), _binding(pins.size()) {}
// these are just diagnostics for testing the class
std::ostream& printPins(std::ostream &out) {
for (auto i : _relay)
out << i << ' ';
out << std::endl;
}
std::ostream& printBindings(std::ostream &out) {
for (auto i : _binding)
out << i << ' ';
out << std::endl;
}
private:
std::vector<short> _relay;
std::vector<short > _binding;
};
enum {A0=80, A1, A2, A3, A4};
int main()
{
Relay reles{std::vector<short>{11, 10, 9, 8, 7, 3, 2, 73,
4, A0, A1, A2, A3, A4}};
reles.printPins(std::cout);
reles.printBindings(std::cout);
return 0;
}
enum
для A0
через A4
линии просто для полноты картины в этом примере, но они могут быть #define
или const int
декларации. Это не имеет значения.
Две функции print...()
предназначены только для иллюстрации, чтобы продемонстрировать, что она фактически делает то, что ожидается. В этом случае выход:
11 10 9 8 7 3 2 73 4 80 81 82 83 84
0 0 0 0 0 0 0 0 0 0 0 0 0 0
std::vector является частью стандартной библиотеки и может быть использована, даже если вы не используете C++ 11. Если да, то вы можете воспользоваться такими интересными вещами, как move семантика и constexpr и другие лакомства, которые особенно полезны во встроенных системах. Одна из таких приятных функций называется инициализацией списка и используется в пределах main
в этом примере программы. В этой строке:
Relay reles{std::vector<short>{11, 10, 9, 8, 7, 3, 2, 73, 4, A0, A1, A2, A3, A4}};
Временный std::vector<short>
создается, а затем используется для инициализации reles
экземпляров класса. Умный компилятор может при определенных обстоятельствах оптимизировать создание таких временных рядов. Как всегда, просмотр фактического выхода ассемблера полезен для оценки конкретных методов и конкретных компиляторов.
Еще одна вещь, которую я нахожу очень полезной, - это стиль for (auto i : _relay)
for
. Это говорит, что компилятор автоматически выводит тип для i
, обрабатывая relay
как коллекцию чего-то. Очень кратким и очень удобным.
Если вы еще не знакомы с языком C++ (или только относительно новыми частями), я бы рекомендовал получить книгу, такую как Stroustrup's Язык программирования C++, четвертый редактор..
Edit: В прискорбном случае, что у вас есть очень ограниченный компилятор C++, так как, кажется, the situation с Arduino, вам нужно сделать что-то по-другому. В частности, поскольку у вас нет operator new
или operator delete
, вам придется либо предварительно выделить некоторый максимальный размер для своих массивов, либо просто полагаться на те, которые передаются как часть инициализации. Вот один из способов сделать это:
#include <cassert>
class Relay
{
public:
Relay(int numpins, short *pins, short *bindings)
: _numpins(numpins), _relay(pins), _binding(bindings) {}
short pin(int i)
{
if ((i < 0) || (i >= _numpins))
return -1;
return _relay[i];
}
short binding(int i)
{
if ((i < 0) || (i >= _numpins))
return -1;
return _binding[i];
}
private:
int _numpins;
short *_relay;
short *_binding;
};
enum {A0=80, A1, A2, A3, A4};
int main()
{
const int numpins = 14;
short pins[numpins] = {11, 10, 9, 8, 7, 3, 2, 73,
4, A0, A1, A2, A3, A4};
short bindings[numpins] = {1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14};
Relay reles(numpins, pins, bindings);
assert(reles.pin(0) == 11);
assert(reles.binding(4) == 5);
return 0;
}
Откуда взялась длина()? – Joky
Я забыл опубликовать эту функцию, теперь обновленную. –
Вы не можете передать массив функции в C++. Это ухудшает указатель, поэтому ваша функция 'length()' неверна (это должно быть очевидно, если вы объявляете '_relay' (соответственно) в качестве указателя. –