我目前正在使用C ++开发一个小型私有项目,我想出了以下结构:
#include <iostream>
class A
{
std::vector<int> vec;
protected:
virtual bool onAdd(int toAdd) {
// should the 'adding' be suppressed?
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return false;
}
public:
void add(int i) {
if(!onAdd(i)) {
// actual logic
vec.push_back(i);
}
}
};
class B : public A
{
protected:
bool onAdd(int toAdd) override {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
在这个例子中,onAdd
基本上是add
的回调,但是以更多态的方式。
如果课程C
继承自B
并且想要覆盖onAdd
,则会出现实际问题。在这种情况下,在调用C::add
时,B中的实现将被丢弃(即不被调用)。所以基本上我想要实现的是类似构造函数的行为,我可以在类层次结构中的不同位置覆盖相同的方法,并且所有这些都被调用。
我现在的问题是:是否有可能/设计来实现这一目标?但我确信它不会像级联构造函数那样容易。
注意:不要过分关注add
示例。问题是关于回调的结构,而不是add
。
答案 0 :(得分:3)
我只会打电话给父母onAdd()
GROUP BY AccountNumber, CurrentBalance, A.ActualTagDeposit
如果您希望其他开发人员从您的基类继承,这可能会有点混乱。但对于小型私有层次结构,它可以完美运行。
我有时会使用using语句来使其更明确
bool C::onAdd(int toAdd) {return my_answer && B::onAdd(toAdd);}
答案 1 :(得分:2)
struct RunAndDiscard {
template<class Sig, class...Args>
void operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return;
for (auto* i = start; i != (finish-1); ++i) {
(*i)(args...);
}
(*(finish-1))(std::forward<Args>(args)...);
}
};
template<class Sig, class Combine=RunAndDiscard>
struct invokers {
std::vector<Sig*> targets;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return Combine{}( targets.data(), targets.data()+targets.size(), std::forward<Args>(args)... );
}
};
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
这会创建一个每个实例的待办事项表onAdd
。
创建每类表更难;你需要使用父类型的表来链接你的表,这需要每类的样板。
没有办法让C ++编译器编写每个实例版本或每个类版本,而无需自己编写。
有C ++ 20提案涉及反思和具体化,加上元类提议,可能涉及自动编写这样的代码(基于每个实例和每个类)。
Here是这项测试技术的实例:
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
class A {
std::vector<int> vec;
protected:
invokers<bool(A*, int), AndTogetherResultWithShortCircuit> onAdd;
public:
void add(int i) {
if (!onAdd(this, i)) {
vec.push_back(i);
}
}
};
class B : public A
{
public:
B() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "B::onAdd(" << x << ")" << std::endl;
return x%2;
});
}
};
class C : public B
{
public:
C() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "C::onAdd(" << x << ")" << std::endl;
return false;
});
}
};
当你想编写自己的OO系统时,可以用C ++编写,但C ++不会为你编写它。
答案 2 :(得分:1)
如果你想要一个通用的解决方案,也许你可以使用CRTP和可变参数模板而不是运行时多态性。
从this answer和this answer获取灵感:
template<class... OnAdders> class A : private OnAdders... {
std::vector<int> vec;
template<class OnAdder>
bool onAdd(int toAdd){
return static_cast<OnAdder*>(this)->onAdd(toAdd);
}
template<typename FirstOnAdder, typename SecondOnAdder, class... RestOnAdders>
bool onAdd(int toAdd){
if (onAdd<FirstOnAdder>(toAdd))
return true;
return onAdd<SecondOnAdder, RestOnAdders...>(toAdd);
}
public:
void add(int i) {
if (onAdd<OnAdders...>(i))
return;
// actual logic
vec.push_back(i);
}
};
class B {
public:
bool onAdd(int toAdd) {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
您可以使用:
A<B,C> a;
a.add(42);
答案 3 :(得分:0)
以下解决方案使用std::function
在每个构造函数中添加每个回调:
#include <iostream>
#include <vector>
#include <functional>
class A
{
std::vector<int> vec;
protected:
bool onAdd(int toAdd)
{
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return true;
}
// vector of callback functions. Initialized with A::onAdd() callback as the first entry
std::vector<std::function<bool(int)>> callbacks{{[this](int toAdd){return onAdd(toAdd); }}};
public:
void add(int i)
{
for(auto& callback : callbacks) {
if(!callback(i))
return;
}
// actual logic
vec.push_back(i);
}
};
class B : public A
{
public:
B()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return true;
}
};
class C : public B
{
public:
C()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some C specific checks
std::cout << "C::onAdd()" << std::endl;
// must also call B::onAdd()
return true;
}
};
int main()
{
C c;
c.add(5);
}
打印:
A::onAdd()
B::onAdd()
C::onAdd()