C++ 条件成员函数执行
假设您有一个带有函数C++ 条件成员函数执行,c++,C++,假设您有一个带有函数Foo::bar()的类Foo。 围绕此函数的是一个Monitor类,它围绕Foo进行包装,并通过重载operator->转发任何函数调用 此外,Monitor类有一个布尔标志execute。如果execute为true,则所有函数调用 应正常执行Foo的,但如果execute设置为false,则应跳过执行 下面的代码段显示了它的外观: #include <iostream> using namespace std; class Foo { void ba
Foo::bar()
的类Foo
。
围绕此函数的是一个Monitor
类,它围绕Foo
进行包装,并通过重载operator->
转发任何函数调用
此外,Monitor类有一个布尔标志execute
。如果execute
为true,则所有函数调用
应正常执行Foo的,但如果execute
设置为false,则应跳过执行
下面的代码段显示了它的外观:
#include <iostream>
using namespace std;
class Foo {
void bar() {std::cout << "Foo::bar()";}
};
template<typename T> class Monitor<T> {
T& ref;
bool exec;
public:
Monitor(T& obj) : ref(obj), exec(true) {}
T* operator->() {/* if exec */ return &ref;}
void setExec(bool e) {exec = e;}
};
int main() {
Foo foo;
Monitor<Foo> monitor(foo);
monitor->bar(); // call Foo::bar();
monitor.setExec(false);
monitor->bar(); // do nothing
}
#包括
使用名称空间std;
福班{
void bar(){std::cout(){/*if exec*/return&ref;}
void setExec(boole e){exec=e;}
};
int main(){
富富,;
监视器(foo);
monitor->bar();//调用Foo::bar();
monitor.setExec(false);
监视器->栏();//什么也不做
}
这可能实现吗?显而易见的解决方案是有一个基类IFoo
,并且
模拟实现MockFoo
不执行任何操作,然后返回指向MockFoo
对象的指针
当调用操作符->
时,这会使整个过程变得相当僵硬,但您必须这样做
为要监视的任何类提供模拟对象
>,是否有更好的方法来实现这一点?
< P>如果你知道你要调用哪个函数,你可以做如下的事情。这甚至允许在函数<代码> > Exc==false < /COD>中指定函数的默认返回值。我确信我没有考虑所有可能的引用返回参数陷阱,Co。nst成员函数等,但我相信如果您想使用它,您可以对其进行调整#include <iostream>
struct X {
double callX(const int& x){ return x/100.;};
};
struct Y {
int callY(const std::string& y){ return y.length();};
};
template<typename F> class Monitor;
template<typename T, typename Ret, typename ...Args>
class Monitor<Ret(T::*)(Args...)> {
T& ref;
Ret(T::*func)(Args...);
Ret defaultRet;
bool exec;
public:
Monitor(T& ref, Ret(T::*func)(Args...), Ret defaultRet = Ret())
: ref(ref),
func(func),
defaultRet(defaultRet),
exec(true){};
void setExec(bool e) {exec = e;};
Ret call(Args&&... args) {
if(exec)
return (ref.*func)(std::forward<Args>(args)...);
else
return defaultRet;
};
};
template<typename T, typename Ret, typename ...Args>
auto makeMonitor(T& x, Ret(T::*f)(Args...), Ret r = Ret()) {
return Monitor<Ret(T::*)(Args...)>(x,f,r);
}
int main() {
X x;
Y y;
auto xmon = makeMonitor(x, &X::callX);
auto ymon = makeMonitor(y, &Y::callY);
auto ymon_def = makeMonitor(y, &Y::callY, 123);
std::cout << "callX(3)=" << xmon.call(3) << std::endl;
std::cout << "callY(\"hello\")=" << ymon.call("hello") << std::endl;
std::cout << "[default return] callY(\"hello\")=" << ymon_def.call("hello") << std::endl;
xmon.setExec(false);
ymon.setExec(false);
ymon_def.setExec(false);
std::cout << "After setExec(false):" << std::endl;
std::cout << "callX(3)=" << xmon.call(3) << std::endl;
std::cout << "callY(\"hello\")=" << ymon.call("hello") << std::endl;
std::cout << "[default return] callY(\"hello\")=" << ymon_def.call("hello") << std::endl;
return 0;
}
工作示例是
您提到的“显而易见的”解决方案可以简化一点,因此您只需定义一个额外的(模拟)类,而不需要额外的基类。如果您不介意虚拟成员函数造成的轻微性能损失,您可以这样做:
#include <iostream>
struct MockX;
struct X {
typedef MockX mock;
virtual double doX(int x){ return x/100.;};
};
struct MockX : X {
virtual double doX(int x){ return 0.;};
};
struct MockY;
struct Y {
typedef MockY mock;
virtual int doY(std::string y){ return y.length();};
};
struct MockY : Y {
virtual int doY(std::string y){ return 123;};
};
template <typename T>
struct Monitor {
T& ref;
static typename T::mock dummy;
bool exec;
Monitor(T& ref) : ref(ref), exec(true){};
void setExec(bool e){exec = e;};
T* operator->(){
if(exec)
return &ref;
else
return &dummy;
};
};
template<typename T>
typename T::mock Monitor<T>::dummy{};
int main() {
X x;
Y y;
auto xmon = Monitor<X>(x);
auto ymon = Monitor<Y>(y);
std::cout << "doX(3)=" << xmon->doX(3) << std::endl;
std::cout << "doY(\"hello\")=" << ymon->doY("hello") << std::endl;
xmon.setExec(false);
ymon.setExec(false);
std::cout << "After setExec(false):" << std::endl;
std::cout << "doX(3)=" << xmon->doX(3) << std::endl;
std::cout << "doY(\"hello\")=" << ymon->doY("hello") << std::endl;
return 0;
}
#包括
结构MockX;
结构X{
typedef MockX mock;
虚拟双doX(intx){返回x/100;};
};
结构MockX:X{
虚双doX(intx){返回0;};
};
结构模拟;
结构{
typedef MockY mock;
虚拟整数doY(std::string y){返回y.length();};
};
结构MockY:Y{
虚拟int-doY(std::string y){return 123;};
};
模板
结构监视器{
T&ref;
静态类型名T::mock dummy;
bool-exec;
监视器(T&ref):ref(ref),exec(true){};
void setExec(boole e){exec=e;};
T*运算符->(){
如果(执行)
返回&ref;
其他的
返回&虚拟;
};
};
模板
typename T::mock Monitor::dummy{};
int main(){
X;
Y;
自动xmon=监视器(x);
自动ymon=监视器(y);
std::对如何改进我的问题或澄清我的问题没有任何评论吗?我认为如果你想能够调用被监视类的任何成员函数作为monitor->somefunc
,除了模拟类之外没有其他方法。你是从->
操作符返回T*
,因此,不管它是什么,它都必须提供somefuncde>,否则它甚至无法编译。如果您只想调用受监视类的特定方法,则可以返回调用该方法的函数对象(如果标志为false,则返回空的伪函数),而不是类本身(可能不使用->
运算符)。您的想法告诉我这是多么困难(特别是当您必须处理返回类型时…)。我的目标是保持接口透明,因此调用pX->callX()
或monitrox->callX()
没有区别。我认为这真的不可能(因为您无法通过编程更改类)。可能是您的“显而易见的解决方案”是最好的…我会想办法让这种方法更方便。最后我使用了模拟方法。因为我已经有了一个带有基类的类结构,所以没有太大的变化。可惜没有其他方法。。。
#include <iostream>
struct MockX;
struct X {
typedef MockX mock;
virtual double doX(int x){ return x/100.;};
};
struct MockX : X {
virtual double doX(int x){ return 0.;};
};
struct MockY;
struct Y {
typedef MockY mock;
virtual int doY(std::string y){ return y.length();};
};
struct MockY : Y {
virtual int doY(std::string y){ return 123;};
};
template <typename T>
struct Monitor {
T& ref;
static typename T::mock dummy;
bool exec;
Monitor(T& ref) : ref(ref), exec(true){};
void setExec(bool e){exec = e;};
T* operator->(){
if(exec)
return &ref;
else
return &dummy;
};
};
template<typename T>
typename T::mock Monitor<T>::dummy{};
int main() {
X x;
Y y;
auto xmon = Monitor<X>(x);
auto ymon = Monitor<Y>(y);
std::cout << "doX(3)=" << xmon->doX(3) << std::endl;
std::cout << "doY(\"hello\")=" << ymon->doY("hello") << std::endl;
xmon.setExec(false);
ymon.setExec(false);
std::cout << "After setExec(false):" << std::endl;
std::cout << "doX(3)=" << xmon->doX(3) << std::endl;
std::cout << "doY(\"hello\")=" << ymon->doY("hello") << std::endl;
return 0;
}