在 class 函数中初始化外部作用域变量
Initialize outer scope variable in class function
我是 C++ 新手,我有 C# 背景。由于 https://docs.platformio.org/ .
,我正在使用 VS 代码使用 C++ 创建一个 Arduino 项目
以下代码可以工作并打开我的 LED 灯条:
main.cpp
#include <Arduino.h>
#include <LedStrip.h>
// pin where led strip is connected
#define LED_STIP_PIN 4
// number of leds in the strip
#define LED_STRIP_COUNT 7
// My wrapper class
LedStrip myLedStripWrapper;
void setup() {
// empty
}
void loop() {
myLedStripWrapper.setup(LED_STRIP_COUNT, LED_STIP_PIN);
// myLedStripWrapper.foo1(); // <<<HERE-1>>>
// wait forever
while (true) {
delay(1);
}
}
LedStrip.h
#include <Adafruit_NeoPixel.h>
class LedStrip
{
public:
Adafruit_NeoPixel strip;
void setup(uint16_t led_count, uint16_t pin)
{
// Declare our NeoPixel strip object:
Adafruit_NeoPixel a(led_count, pin, NEO_GRB + NEO_KHZ800);
strip = a;
// INITIALIZE NeoPixel strip
strip.begin();
strip.show();
strip.setBrightness(15);
foo1(); // <<<HERE-2>>> <------------------- calling foo1 from here turns on the led strip
}
// Color led strip blue
void foo1()
{
uint32_t color = strip.Color(0, 0, 100);
for (uint16_t i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
// delay(100);
}
}
};
请注意,在代码中我有标签 <<<HERE-1>>>
和 <<<HERE-2>>>
。我想从 <<<HERE-1>>>
调用函数 foo1
。 为什么如果我取消注释 <<<HERE-1>>>
并注释 <<<HERE-2>>>
代码不起作用并且 LED 灯条不亮? 换句话说我不想从 class 包装器中调用 foo1。我只是从那里调用它,因为它只有在我从那里调用它时才有效。
那个 class 的作者犯了一个小学 C++ 错误,没有正确观察 Rule of Three。这意味着可以在不安全的情况下复制 Adafruit_NeoPixel
对象。
void setup(uint16_t led_count, uint16_t pin)
{
// Declare our NeoPixel strip object:
Adafruit_NeoPixel a(led_count, pin, NEO_GRB + NEO_KHZ800);
strip = a; // copy here. Both a and strip point to a shared resource
// INITIALIZE NeoPixel strip
strip.begin();
strip.show();
strip.setBrightness(15);
} // a goes out of scope here and frees the shared resource in its
// destructor. Oops.
最简单的解决方法是在 LedStrip
的构造函数中初始化 strip
,而无需复制它。
为了确保 strip
不被复制,您将不得不阻止 LedStrip
被复制或实现允许 LedStrip
被复制而不复制的特殊成员函数strip
。在下面的示例中,我将简单地防止复制。
如果需要复制,请考虑将 Adafruit_NeoPixel strip;
替换为 std::shared_ptr<Adafruit_NeoPixel> strip;
,以便复制指针而不是复制时会变成炸弹的对象。
class LedStrip
{
public:
Adafruit_NeoPixel strip; // you sure you want this public?
// adding constructor so we don't have to copy a Adafruit_NeoPixel object
LedStrip(uint16_t led_count, uint16_t pin):
strip(led_count, pin, NEO_GRB + NEO_KHZ800) // this is a member initializer list
// It allows us to construct strip
// without having to copy anything.
// more on that later
{
// INITIALIZE NeoPixel strip
strip.begin();
strip.show();
strip.setBrightness(15);
}
// preventing copying of LedStrip
LedStrip(const LedStrip& ) = delete;
LedStrip & operator=(const LedStrip& ) = delete;
// note if the compiler doesn't like the = delete, remove it, make
// the copy constructor and assignment operator private, and do not
// implement them
// Color led strip blue
void foo1()
{
uint32_t color = strip.Color(0, 0, 100);
for (uint16_t i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
// delay(100);
}
}
private:
/* only needed if the = delete trick above doesn't work.
LedStrip(const LedStrip& );
LedStrip & operator=(const LedStrip& );
*/
};
然后
LedStrip myLedStripWrapper;
变成
LedStrip myLedStripWrapper(LED_STRIP_COUNT, LED_STIP_PIN);
和
myLedStripWrapper.setup(LED_STRIP_COUNT, LED_STIP_PIN);
从世界上消失,再也不会出现。
我是 C++ 新手,我有 C# 背景。由于 https://docs.platformio.org/ .
,我正在使用 VS 代码使用 C++ 创建一个 Arduino 项目以下代码可以工作并打开我的 LED 灯条:
main.cpp
#include <Arduino.h>
#include <LedStrip.h>
// pin where led strip is connected
#define LED_STIP_PIN 4
// number of leds in the strip
#define LED_STRIP_COUNT 7
// My wrapper class
LedStrip myLedStripWrapper;
void setup() {
// empty
}
void loop() {
myLedStripWrapper.setup(LED_STRIP_COUNT, LED_STIP_PIN);
// myLedStripWrapper.foo1(); // <<<HERE-1>>>
// wait forever
while (true) {
delay(1);
}
}
LedStrip.h
#include <Adafruit_NeoPixel.h>
class LedStrip
{
public:
Adafruit_NeoPixel strip;
void setup(uint16_t led_count, uint16_t pin)
{
// Declare our NeoPixel strip object:
Adafruit_NeoPixel a(led_count, pin, NEO_GRB + NEO_KHZ800);
strip = a;
// INITIALIZE NeoPixel strip
strip.begin();
strip.show();
strip.setBrightness(15);
foo1(); // <<<HERE-2>>> <------------------- calling foo1 from here turns on the led strip
}
// Color led strip blue
void foo1()
{
uint32_t color = strip.Color(0, 0, 100);
for (uint16_t i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
// delay(100);
}
}
};
请注意,在代码中我有标签 <<<HERE-1>>>
和 <<<HERE-2>>>
。我想从 <<<HERE-1>>>
调用函数 foo1
。 为什么如果我取消注释 <<<HERE-1>>>
并注释 <<<HERE-2>>>
代码不起作用并且 LED 灯条不亮? 换句话说我不想从 class 包装器中调用 foo1。我只是从那里调用它,因为它只有在我从那里调用它时才有效。
那个 class 的作者犯了一个小学 C++ 错误,没有正确观察 Rule of Three。这意味着可以在不安全的情况下复制 Adafruit_NeoPixel
对象。
void setup(uint16_t led_count, uint16_t pin)
{
// Declare our NeoPixel strip object:
Adafruit_NeoPixel a(led_count, pin, NEO_GRB + NEO_KHZ800);
strip = a; // copy here. Both a and strip point to a shared resource
// INITIALIZE NeoPixel strip
strip.begin();
strip.show();
strip.setBrightness(15);
} // a goes out of scope here and frees the shared resource in its
// destructor. Oops.
最简单的解决方法是在 LedStrip
的构造函数中初始化 strip
,而无需复制它。
为了确保 strip
不被复制,您将不得不阻止 LedStrip
被复制或实现允许 LedStrip
被复制而不复制的特殊成员函数strip
。在下面的示例中,我将简单地防止复制。
如果需要复制,请考虑将 Adafruit_NeoPixel strip;
替换为 std::shared_ptr<Adafruit_NeoPixel> strip;
,以便复制指针而不是复制时会变成炸弹的对象。
class LedStrip
{
public:
Adafruit_NeoPixel strip; // you sure you want this public?
// adding constructor so we don't have to copy a Adafruit_NeoPixel object
LedStrip(uint16_t led_count, uint16_t pin):
strip(led_count, pin, NEO_GRB + NEO_KHZ800) // this is a member initializer list
// It allows us to construct strip
// without having to copy anything.
// more on that later
{
// INITIALIZE NeoPixel strip
strip.begin();
strip.show();
strip.setBrightness(15);
}
// preventing copying of LedStrip
LedStrip(const LedStrip& ) = delete;
LedStrip & operator=(const LedStrip& ) = delete;
// note if the compiler doesn't like the = delete, remove it, make
// the copy constructor and assignment operator private, and do not
// implement them
// Color led strip blue
void foo1()
{
uint32_t color = strip.Color(0, 0, 100);
for (uint16_t i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
// delay(100);
}
}
private:
/* only needed if the = delete trick above doesn't work.
LedStrip(const LedStrip& );
LedStrip & operator=(const LedStrip& );
*/
};
然后
LedStrip myLedStripWrapper;
变成
LedStrip myLedStripWrapper(LED_STRIP_COUNT, LED_STIP_PIN);
和
myLedStripWrapper.setup(LED_STRIP_COUNT, LED_STIP_PIN);
从世界上消失,再也不会出现。