最初のエラー「no matching ..」は、デフォルトのコンストラクターがないためです。そのアプローチを機能させることができます。
次のように、パラメーターなし、別名デフォルト コンストラクターをクラスに追加します。
class LedControl {
LedControl();
LedControl(uint8_t pin1, uint8_t pin2, uint8_t pin3);
private:
uint8_t pin1;
uint8_t pin2;
uint8_t pin3;
};
LedControl::LedControl() : pin1(0), pin2(0), pin3(0) {
// this constructor leaves the class unusable
}
LedControl::Ledcontrol(uint8_t p1, uint8_t p2, uint8_t p3)
: pin1(p1), pin2(p2), pin3(p3)
{
// this object is ready to use
}
このクラスでは、アプローチは機能しますが、最適な方法ではありません。この行はあまりにも多くの作業を行います:
void setup() {
lc = LedControl(11, 13, 12);// data, clock, latch;
}
このコード行には、コンパイラがコードを作成することが含まれます。
- 最初に、クラスの別のインスタンスが、パラメーター 11、13、12 を使用してスタック上に構築されます。
- 次に、スタック オブジェクトからグローバル オブジェクトにデータをコピーする= 演算子を適用します。
- setup() が終了すると、スタック オブジェクトがフラッシュされます。
一時オブジェクトがスタック上にあるため、プログラムはメモリをあまり使用しませんでしたが、一時オブジェクトを作成してから一時オブジェクトから永続オブジェクトにコピーするための余分な操作が必要になるため、コード サイズが大きくなります。
行の関数を埋めるために、コンパイラが= 演算子を作成していることに注意してください。
lc = LedControl(11, 13, 12);
これは、コンストラクターの内容に応じて機能する場合と機能しない場合があります。コンパイラは、単純な= 演算子が必要であると推測することしかできません。基本的な代入演算子は、すべてのデータ メンバーを = の右側のインスタンスから左側のインスタンスにコピーするだけです。構築されたコンパイラ = にはコードが含まれません。
コンストラクターが重要なこと (パラメーターの保存以外) を行う場合、コンパイラーによって構築された (推測された) 割り当て演算子は、期待どおりに機能しない可能性があります。あなたの場合、コンストラクターはおそらく次のようなピンモードを設定します。
LedControl::LedControl(uint8_t p1, uint8_t p2, uint8_t p3)
: pin1(p1), pin2(p2), pin3(p3)
{
pinMode(pin1, INPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
return;
}
これはたまたま機能しますが、たまたまです。pinMode() 呼び出しは、一時オブジェクトが構築され、グローバルlcからではなく、そのオブジェクトから呼び出されるときに行われます。pinMode() はグローバルであるため、このケースは正しい目標を達成しますが、期待した方法ではない可能性があります。割り込みハンドラの登録などのより複雑な操作については、独自の代入演算子を作成する必要があります。
LedControl& operator= (const LedControl & other);
その方法では、グローバルlcの状態が必要なものであることを確認できます。より簡単で安全なアプローチは、それをまったく扱わないことです。
シンプルで効率的なアプローチは、他のライブラリで見たことがあるかもしれませんが、ピンを割り当てるクラスにメソッドを追加することです。
class LedControl {
void attach(uint8_t pin1, uint8_t pin2, uint8_t pin3);
};
void LedControl::attach(uint8_t pin1, uint8_t pin2, uint8_t pin3) {
this.pin1 = pin1;
this.pin2 = pin2;
this.pin3 = pin3;
// do other setup type operations
return;
}
これで、プログラムは空のオブジェクトを構築し、setup() 中にピンを割り当てます。
LedControl lc; // not ready to use until attach pins
void setup() {
lc.attach(11, 13, 12);// data, clock, latch;
...
}
これには、一時オブジェクトの構築も代入演算子も含まれません。設計に関して、一部の人々は、ユーザーが attach() を呼び出すのを忘れて、グローバル lc オブジェクトを使用できないままにしておく可能性があるとかなりコメントするかもしれません。デスクトップ アプリケーションの場合は、その失敗を防ぐためにコードを追加することがあります。組み込みアプリケーションの場合、これは許容できるリスクであり、コード サイズの増加またはメモリの節約によってバランスが取れています。