提供一个指向成员函数的指针,由目标 class 调用而没有函数
Provide a pointer to member function to be invoked by the target class without functional
我阅读了很多关于函数指针、仿函数和回调的问题(和答案),但我仍然不清楚哪种工具适合我。
其中一些不适用于我的场景,因为我的编译器 avr-gcc v5.4.0 似乎没有 C++ 标准库(即 std::function
不可用)。
这是我的基地class:
class Debouncer
{
public:
typedef uint8_t (Debouncer::*debouncer_raw_t) (void);
Debouncer() {}
void setRawFunction(Debouncer::debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw();
// do something
}
}
在我的其他 classes 中,我有:
class Inputs
{
public:
Inputs()
{
_deb.setRawFunction(myRaw);
}
private:
Debouncer _deb;
uint8_t myRaw()
{
return something;
}
}
当然这不会编译,因为 myRaw
不是静态的。
不管怎样,我会尽量避免这种情况,因为它会破坏现有代码。
如果我没记错的话,很多问题似乎都是反过来问的。
相反,我只想将我的成员函数的指针传递给我的 Debouncer
class,以便它可以在需要时调用 _raw()
。
Here 我发现了避免 std::
库的建议:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
void userCode(Fred& fred, FredMemFn p) // Use a typedef for pointer-to-member types
{
int ans = CALL_MEMBER_FN(fred,p)('x', 3.14);
// Would normally be: int ans = (fred.*p)('x', 3.14);
// ...
}
但似乎恰恰相反。这里的 class Fred
是我的 Debouncer
。
我不想呼叫 Debouncer
成员,而是 caller class 的成员(即 Input::myRaw()
)。
能否请您帮助我了解实现如此简单任务的正确工具?
如果您知道(或要求)每个使用 Debouncer
的 class 都有一个 public myRaw()
函数(或更好的 operator()
,或者实际上还有别的),问题更简单:
template <typename T>
class Debouncer
{
public:
Debouncer (T* t): _t(t) {}
void anotherFunction()
{
uint8_t value = _t->myRaw();
std::cout << static_cast<int>(value);
}
private:
T* _t;
};
class Inputs
{
public:
Inputs() : _deb(this)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs> _deb;
};
int main()
{
Inputs i;
i.foo();
}
这将是 C++ 中的首选解决方案。例如,参见标准库 <algorithm>
- 任何采用谓词或其他可调用函数的函数都希望使用 operator()
来调用它,而不是必须处理指向成员函数的指针。
如果你不知道应该调用什么函数并且你真的不能对 class 施加任何要求,你需要存储指向 class 的指针(或引用)和指向成员函数的指针。请注意,您不能将指针连接到不同 class 的成员函数,因此我们再次需要模板:
template <typename T, typename Func>
class Debouncer
{
public:
Debouncer (T* t, Func f): _t(t), _f(f) {}
void anotherFunction()
{
uint8_t value = (_t->*_f)(); //I get it now why isocpp asks to use macro here, the syntax is horrible
std::cout << static_cast<int>(value);
}
private:
T* _t;
Func _f;
};
class Inputs
{
public:
Inputs() : _deb(this, &Inputs::myRaw)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs, decltype(&Inputs::myRaw)> _deb; //decltype is C++11, you could also declare type like you did in your question
};
int main()
{
Inputs i;
i.foo();
}
创建成员函数 virtual
是一种开销相对较低的方法,可以让单个指针(指向对象)同时引用对象的数据和正确的成员函数。
class InputsBase
{
// All classes that implement myRaw() should inherit from this class
public:
virtual uint8_t myRaw() = 0;
};
class Inputs : public InputsBase
{
public:
Inputs()
{
_deb.setRawFunction(this);
}
private:
Debouncer _deb;
virtual uint8_t myRaw()
{
return something;
}
}
您的 Debouncer 然后可以简单地存储指向相关对象的指针。
class Debouncer
{
public:
typedef InputsBase* debouncer_raw_t;
Debouncer() {}
void setRawFunction(debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw->myRaw();
// do something
}
}
我阅读了很多关于函数指针、仿函数和回调的问题(和答案),但我仍然不清楚哪种工具适合我。
其中一些不适用于我的场景,因为我的编译器 avr-gcc v5.4.0 似乎没有 C++ 标准库(即 std::function
不可用)。
这是我的基地class:
class Debouncer
{
public:
typedef uint8_t (Debouncer::*debouncer_raw_t) (void);
Debouncer() {}
void setRawFunction(Debouncer::debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw();
// do something
}
}
在我的其他 classes 中,我有:
class Inputs
{
public:
Inputs()
{
_deb.setRawFunction(myRaw);
}
private:
Debouncer _deb;
uint8_t myRaw()
{
return something;
}
}
当然这不会编译,因为 myRaw
不是静态的。
不管怎样,我会尽量避免这种情况,因为它会破坏现有代码。
如果我没记错的话,很多问题似乎都是反过来问的。
相反,我只想将我的成员函数的指针传递给我的 Debouncer
class,以便它可以在需要时调用 _raw()
。
Here 我发现了避免 std::
库的建议:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
void userCode(Fred& fred, FredMemFn p) // Use a typedef for pointer-to-member types
{
int ans = CALL_MEMBER_FN(fred,p)('x', 3.14);
// Would normally be: int ans = (fred.*p)('x', 3.14);
// ...
}
但似乎恰恰相反。这里的 class Fred
是我的 Debouncer
。
我不想呼叫 Debouncer
成员,而是 caller class 的成员(即 Input::myRaw()
)。
能否请您帮助我了解实现如此简单任务的正确工具?
如果您知道(或要求)每个使用 Debouncer
的 class 都有一个 public myRaw()
函数(或更好的 operator()
,或者实际上还有别的),问题更简单:
template <typename T>
class Debouncer
{
public:
Debouncer (T* t): _t(t) {}
void anotherFunction()
{
uint8_t value = _t->myRaw();
std::cout << static_cast<int>(value);
}
private:
T* _t;
};
class Inputs
{
public:
Inputs() : _deb(this)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs> _deb;
};
int main()
{
Inputs i;
i.foo();
}
这将是 C++ 中的首选解决方案。例如,参见标准库 <algorithm>
- 任何采用谓词或其他可调用函数的函数都希望使用 operator()
来调用它,而不是必须处理指向成员函数的指针。
如果你不知道应该调用什么函数并且你真的不能对 class 施加任何要求,你需要存储指向 class 的指针(或引用)和指向成员函数的指针。请注意,您不能将指针连接到不同 class 的成员函数,因此我们再次需要模板:
template <typename T, typename Func>
class Debouncer
{
public:
Debouncer (T* t, Func f): _t(t), _f(f) {}
void anotherFunction()
{
uint8_t value = (_t->*_f)(); //I get it now why isocpp asks to use macro here, the syntax is horrible
std::cout << static_cast<int>(value);
}
private:
T* _t;
Func _f;
};
class Inputs
{
public:
Inputs() : _deb(this, &Inputs::myRaw)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs, decltype(&Inputs::myRaw)> _deb; //decltype is C++11, you could also declare type like you did in your question
};
int main()
{
Inputs i;
i.foo();
}
创建成员函数 virtual
是一种开销相对较低的方法,可以让单个指针(指向对象)同时引用对象的数据和正确的成员函数。
class InputsBase
{
// All classes that implement myRaw() should inherit from this class
public:
virtual uint8_t myRaw() = 0;
};
class Inputs : public InputsBase
{
public:
Inputs()
{
_deb.setRawFunction(this);
}
private:
Debouncer _deb;
virtual uint8_t myRaw()
{
return something;
}
}
您的 Debouncer 然后可以简单地存储指向相关对象的指针。
class Debouncer
{
public:
typedef InputsBase* debouncer_raw_t;
Debouncer() {}
void setRawFunction(debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw->myRaw();
// do something
}
}