[英]Arduino C++ class with arrays
我正在建立一个应该包含数组的类。 我目前正在尝试传递一个数组,但是该数组可以是任何大小。 当我尝试这样做时,它不起作用。 有谁知道该怎么做? 我目前遇到了一些麻烦,但这是我的代码:
Relay.cpp
Relay::Relay(short pins[])
{
_relay = pins;
_binding = new short[length()];
for(short i=0; i<length(); i++)
_binding[i]=0;
}
short Relay::length()
{
return sizeof(_relay)/sizeof(short);
}
Relay.h
class Relay
{
public:
Relay(short pins[]);
short length();
private:
short *_relay;
short *_binding;
};
当我创建实例时:
Relay reles((short[]){11, 10, 9, 8, 7, 3, 2, 73, 4, A0, A1, A2, A3, A4});
编辑:在常驻饼干的建议之后,我最终得到了像这样的cpp文件,但它给了我对`operator new [](unsigned int)错误的未定义引用。 此外,当我尝试访问_pins并显示_pins [i]中使用的内容时,它不会显示我在实例上传递的内容。 例如,如果我显示_pins [0]上的内容,则应返回11,但不是。
如果要使用此方法,则需要分配一些内存。
_bindings = new short[size];
完成操作后,请不要忘记释放此内存。
delete[] _bindings;
在C ++中的动态数组位于名称vector下。 您拨打的电话将变成:
class Relay
{
public:
Relay(const std::vector<short> &pins)
: _binding(pins.size()), _relay(pins) {}
private:
std::vector<short> _relay;
std::vector<short> _binding;
};
int main() {
// C++ 11
// Relay r({1, 2, 3, 4});
// C++03
short arr[] = {1, 2, 3, 4};
std::vector<short> v(std::begin(arr), std::end(arr));
Relay r(v);
}
您的代码中存在多个问题,例如:
short *_relay;
是一个指针,sizeof(_relay)是指针的大小,与它指向的内存分配的大小无关。 所以sizeof(_relay)/ sizeof(short); 等价于sizeof(short *)/ sizeof(short); 这真的没有任何意义。
当您这样做时:
_relay = _pins;
您正在复制一个指针,现在_relay指向同一位置_pins点。 但是,他们指向的内存是“易失性”的:这是您在呼叫站点分配的临时内存。 呼叫返回后,它将立即取消分配。 您的指针现在指向您不应再访问的区域。
通常,使C ++类包含指向“外部数据”的指针是可疑的类设计。 通常,更好的方法是让C ++使用外部数据的副本,因此很明显,当销毁类实例时,内存将被取消分配。
就像其他人提到的那样,其中某些事情使用C ++ 11更容易完成。 如果您使用g++
或clang++
作为编译器,则可能已经支持C ++ 11,这使很多事情变得非常轻松便捷,尤其是对于嵌入式系统而言。
在这种特殊情况下,这是一个完整且可编译的程序(我使用g++
并使用g++ -std=c++11 -o relay relay.cpp
进行了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;
}
在此示例中, A0
到A4
行的enum
仅是为了完整性,但它们可能是#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,也可以使用它。 如果您愿意,那么您可以利用诸如移动语义和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
循环的for (auto i : _relay)
样式。 这告诉编译器通过将relay
视为某物的集合来自动推断i
的类型。 非常简洁,非常方便。
如果您还不熟悉C ++语言(或者只是相对较新的部分),我建议您买一本书,例如Stroustrup的The C ++ Programming Language,第四版。 。
编辑 :在不幸的情况下,您的C ++编译器非常有限,就像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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.