繁体   English   中英

带有数组的Arduino C ++类

[英]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;
}

在此示例中, A0A4行的enum仅是为了完整性,但它们可能是#defineconst 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 newoperator 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM