初心者〜C++はこちら。私はA Deeper Look at Signals and Slotsを読んでいました.1)コールバックは本質的に型が安全ではないと主張しています.2)安全にするために、関数の周りに純粋な仮想クラスラッパーを定義する必要があります。私はなぜそれが本当であるか理解するのは難しいです。例として、ここでのコードQtは自分tutorial page for signals and slotsに提供されています。ここではシグナルとスロットは単純な古いコールバックよりも優れているのはなぜですか?
// Header file
#include <QObject>
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int m_value;
};
// .cpp file
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(value);
}
}
// Later on...
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));
a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48
は、コールバックを使用して書き直すことコードです:
#include <functional>
#include <vector>
class Counter
{
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
std::vector<std::function<void(int)>> valueChanged;
void setValue(int value);
private:
int m_value;
};
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
for (auto func : valueChanged) {
func(value);
}
}
}
// Later on...
Counter a, b;
auto lambda = [&](int value) { b.setValue(value); };
a.valueChanged.push_back(lambda);
a.setValue(12);
b.setValue(48);
あなたが見ることができるように、コールバックのバージョンがタイプセーフされ、短いですQtバージョンよりも、despite them claiming that it's notです。 Counter
以外の新しいクラスは定義しません。標準ライブラリコードのみを使用し、特別なコンパイラ(moc)を使用する必要はありません。なぜ、コールバックよりもシグナルとスロットのほうが好まれますか? C++ 11は単にこれらの概念を廃止しましたか?
ありがとうございました。
QtはC++ 11よりもずっと古いです。 Qtのドキュメントやホワイトペーパーなどのクレームは、C++ 11以前の「C++としてのC++」の主張として読まれなければなりません。特に、「コールバックには2つの根本的な欠陥があります。まず第一に、タイプセーフではありません。 C++にとって意味をなさないのはC++です:これを理解するには、純粋なCプログラミングの観点から考える必要があります。 –
"Qtの信号とスロットの実装"と "信号とスロット"のコンセプトを融合させないでください。コールバックのリストとして何かが維持され、イベントが発生したときにコールバックします。あなたはシグナルとスロットの本質を持っています。それ以外はすべて砂糖、構文、マーケティングです。あなたが持っているのは、信号とスロットシステムの単純化されていれば、うまく実装されていることです。 – GManNickG
@ GManNickG次に、実装とQtの違いは何ですか? –