[英]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.