我正在編寫一些arduino代碼,但事情並沒有完全打算。
我在這裏做錯了什麼?我已經閱讀並試圖教育自己關於虛擬功能,但也許我錯過了一些東西。前往QUESTIONSHERE查看需要解答的實際問題,但首先需要解釋一下:不像預期的那樣運行多態類
RGBPixel類和colorGenerator類都是從colorSource派生的,它提供了公共函數getR(),getG()和getB()另一個像素或顏色修改器可以獲取其當前顏色的副本。
從colorGenerator派生的類實現顏色生成代碼,以便它們可以生成它們自己的顏色,而RGBPixels具有colorSource *父成員,因此它們可以從colorGenerator或另一個RGBPixel獲取顏色值。
在我的例子中,我有一個colorGenerator子類(CG_EmeraldWaters,它應該爲我創建各種綠色和藍色),然後是數組中的一些RGBPixels。 RGBPixels [0]應從GC_EmeraldWaters的實例中獲取其值,而RGBPixels [1]從[1],[n]中的[1],[n]的RGBPixels [0],[2]中獲取其值。這些像素似乎是從父母那裏拉出一種顏色,但是鏈中的第一個像素沒有正確查詢colorGenerator,或者colorGenerator沒有正確更新。
要更新colorGenerator,一個colorController類監督的全過程:
colorController.h:
#ifndef _COLORCONTROLLER_H
#define _COLORCONTROLLER_H
#include <list>
#include "colorGenerator.h"
#include "RGBPixel.h"
#include "globals.h"
#include "Arduino.h"
unsigned long millis();
typedef std::list<colorGenerator> generatorList;
class colorController
{
public:
virtual bool refresh();
protected:
generatorList generators;
};
#endif //_COLORCONTROLLER_H
正如你所看到的,控制器具有colorGenerators和方法刷新他們所有的列表(從循環中調用()),其除非在子類中重寫,這是否:
bool colorController::refresh()
{
for (generatorList::iterator it = generators.begin(); it != generators.end(); ++it)
it->refresh();
bool dirty = false;
for (int i = NUM_OF_LEDS-1; i >= 0; --i)
dirty |= RGBPixels[i].refresh();
return dirty;
}
的CC_Cascade類(來自colorController衍生)組事情是這樣的:
CC_Cascade.h
#ifndef _CC_CASCADE_H
#define _CC_CASCADE_H
#include "colorController.h"
class CC_Cascade : public colorController
{
public:
CC_Cascade();
~CC_Cascade();
};
#endif //_CC_CASCADE_H
CC_Cascade.cpp
#include "CC_Cascade.h"
#include "CG_EmeraldWaters.h"
CC_Cascade::CC_Cascade()
{
colorGenerator * freshBubblingSpring = new CG_EmeraldWaters();
generators.push_back(*freshBubblingSpring);
RGBPixels[0].setParent(freshBubblingSpring);
RGBPixels[0].setDelay(40);
for (int i = 1; i < NUM_OF_LEDS; ++i)
{
RGBPixels[i].setParent(&RGBPixels[i-1]);
RGBPixels[i].setDelay(500-(9*i)); //FIXME: magic number only works for 50ish pixels
}
}
CC_Cascade::~CC_Cascade()
{
//TODO: delete generators
}
到目前爲止清楚了嗎? 讓我把注意力放在colorController :: refresh()函數上。應該發生的是,每次調用時,生成器列表中都有一個colorGenerator(因爲CC_Cascade構造函數將它放在那裏),這是一個CG_EmeraldWaters。當對此(通過迭代器)調用refresh()時,它會調用colorGenerator :: refresh(),然後調用updateColor()。在CG_EmeraldWaters的情況下,這被覆蓋,所以CG_EmeraldWaters :: updateColor應該被調用,給出一個綠松石的顏色。使用一些串行寫入語句進行調試,我可以看到IN FACT colorGenerator :: updateColor()被調用,所以在這種情況下,我期望橙色的顏色,但這些都不影響像素的顏色,這些都是保持在CG_EmeraldWaters構造器中設置的紫色。
做了一些小事,我在colorGenerator :: updateColor()中添加了以下代碼:RGBPixels[0].setColor(255,127,0);
而不是我希望的橙色,第一個像素在紫色和橙色之間快速交替,暗示(恕我直言)我的新代碼行正在做它的工作,但是然後像素從colorGenerator中再次拉出其原始的紫色,並且不知怎的,colorGenerator :: updateColor()不會改變colorGenerator的顏色(因爲我沒有得到編譯錯誤,它在改變什麼?)。
所以我qustions是:(QUESTIONSHERE)
1)我怎樣才能colorSource :: currentR(/ G/B)的值從colorGenerator :: updateColor(),因爲內改變currentR(/ G/B)在colorSource中聲明爲受保護,並且colorGenerator直接從colorSource派生?
2)鑑於CG_EmeraldWaters的一個實例,如果updateColor()在colorGenerator中聲明爲虛擬並在CG_EmeraldWaters中重寫,那麼如何通過colorGenerator :: refresh()調用CG_EmeraldWaters :: updateColor(),CG_EmeraldWaters繼承了CG_EmeraldWaters?
下面是colorGenerator和CG_EmeraldWaters的代碼:
colorSource.h:
#ifndef _COLORSOURCE_H
#define _COLORSOURCE_H
#include "Arduino.h"
#ifdef DEBUG
#include "colorGenerator.h" //FIXME: delete Me
#endif
//#define byte unsigned char
typedef byte colorStorage_t;
class colorSource
{
public:
colorSource();
colorSource(colorStorage_t initialR, colorStorage_t initialG, colorStorage_t initialB);
void setColor(colorStorage_t newR, colorStorage_t newG, colorStorage_t newB);
//TODO: better implementation than this
colorStorage_t getR();
colorStorage_t getG();
colorStorage_t getB();
bool hasChanged();
protected:
colorStorage_t currentR;
colorStorage_t currentG;
colorStorage_t currentB;
bool dirty;
#ifdef DEBUG
friend colorGenerator; //FIXME: delete Me
#endif
};
#endif //_COLORSOURCE_H
colorSource.cpp:
#include "colorSource.h"
colorSource::colorSource()
{
//nothing here
}
colorSource::colorSource(colorStorage_t initialR, colorStorage_t initialG, colorStorage_t initialB)
:
currentR(initialR),
currentG(initialG),
currentB(initialB)
{
//intialised in the list
Serial.println("Constructed Color Source with initial color");
}
void colorSource::setColor(colorStorage_t newR, colorStorage_t newG, colorStorage_t newB)
{
currentR = newR;
currentG = newG;
currentB = newB;
}
colorStorage_t colorSource::getR()
{
return currentR;
}
colorStorage_t colorSource::getG()
{
return currentG;
}
colorStorage_t colorSource::getB()
{
return currentB;
}
bool colorSource::hasChanged()
{
return !dirty;
}
colorGenerator.h:
#ifndef _COLORGENERATOR_H
#define _COLORGENERATOR_H
#include "colorSource.h"
#ifdef DEBUG
#include "RGBPixel.h" //delete me, used for debugging!
#include "globals.h" //and me!
#endif
extern "C" unsigned long millis();
class colorGenerator : public colorSource
{
public:
colorGenerator(colorStorage_t initialR, colorStorage_t initialG, colorStorage_t initialB);
bool refresh();
protected:
virtual void updateColor();
unsigned long nextColorUpdate = 0;
unsigned short delay = 40;
};
#endif //_COLORGENERATOR_H
colorGenerator.cpp:
#include "Arduino.h"
#include "colorGenerator.h"
colorGenerator::colorGenerator(colorStorage_t initialR, colorStorage_t initialG, colorStorage_t initialB)
:
colorSource(initialR,initialG,initialB)
{
//intialised in the list
//Serial.println("Constructed Color Generator");
}
bool colorGenerator::refresh()
{
#ifdef DEBUG
Serial.print("colorGenerator::refresh()");
#endif
if (millis() < nextColorUpdate)
return false;
nextColorUpdate = millis() + (unsigned long) delay;
this->updateColor();
return true;
}
void colorGenerator::updateColor() //this function gets called (even if it has been overridden in a child class), but the code in it doesn't have the desired effect
{
#ifdef DEBUG
//Serial.print("colorGenerator::updateColor()");
//RGBPixels[0].setColor(255,127,0);
#endif
currentR = random(127,255);
currentG = random(0,127);
currentB = 0;
}
CG_EmeraldWaters.h:
#ifndef _CG_EMERALDWATERS_H
#define _CG_EMERALDWATERS_H
#include "colorGenerator.h"
#include "globals.h"
#include "RGBPixel.h"
class CG_EmeraldWaters : public colorGenerator
{
public:
CG_EmeraldWaters();
protected:
void updateColor();
};
#endif //_CG_EMERALDWATERS_H
CG_EmeraldWaters.cpp:
#include "Arduino.h"
#include "CG_EmeraldWaters.h"
CG_EmeraldWaters::CG_EmeraldWaters()
:
colorGenerator(255,0,255) //this color seems to stick! Changes made by updateColor() aren't propogated to the pixels.
{
//initialised in list
//Serial.println("Constructed Emerald Waters");
}
long random(long,long);
void CG_EmeraldWaters::updateColor() //this never seems to be called!
{
currentR = 0;
currentG = random(0,255);
currentB = random(0,255);
}
最後,主要的素描文件:
#include "FastSPI_LED2.h"
#include <StandardCplusplus.h>
#include "colorController.h"
#include "RGBPixel.h"
#include "globals.h"
#include "CC_Cascade.h"
colorController * currentColorController;
RGBPixel RGBPixels[NUM_OF_LEDS];
struct CRGB ledString[NUM_OF_LEDS];
void setup()
{
#ifdef DEBUG
//debugging:
Serial.begin(9600);
Serial.println("In Setup");
#endif
// sanity check delay - allows reprogramming if accidently blowing power w/leds
//delay(2000);
LEDS.setBrightness(8);
LEDS.addLeds<WS2801>(ledString, NUM_OF_LEDS);
currentColorController = new CC_Cascade();
}
void writeValuesToString()
{
for (int i = 0; i < NUM_OF_LEDS; ++i)
ledString[i] = CRGB(RGBPixels[i].getR(),RGBPixels[i].getG(),RGBPixels[i].getB());
LEDS.show();
}
void loop()
{
static bool dirty = false; //indicates whether pixel values have changed since last hardware write
//unsigned long lastHardwareWrite = 0; //time of last hardware write - only do this once per milisecond to avoid flicker (this method doesn't work, still flickers)
dirty |= currentColorController->refresh();
if (dirty)
{
dirty = false;
writeValuesToString();
delay(1); //to prevent flicker
}
}
1。你應該能夠從它的子類中調用超類的私有和受保護的方法,除非我錯過了某些東西。 – splrs
這個問題太大了 - 我很想在第一個代碼片段後停止閱讀,但幸運的是我發現頂部的問題。一般來說,你應該嘗試建立一個小的(最好是微小的)獨立的示例來顯示問題。 – dasblinkenlight