C++ c++;如何定义需要为其他开发人员调用的常量函数顺序
我遇到的问题是,我有几个函数需要按定义的顺序调用——顺序不能是可破坏的。 现在代码需要在我完成代码后继续开发。 我在寻找一些方法来设置某种不可破坏的结构中的函数。 例如,我有:C++ c++;如何定义需要为其他开发人员调用的常量函数顺序,c++,function,C++,Function,我遇到的问题是,我有几个函数需要按定义的顺序调用——顺序不能是可破坏的。 现在代码需要在我完成代码后继续开发。 我在寻找一些方法来设置某种不可破坏的结构中的函数。 例如,我有: function_1() { //do some stuff ..} ; // must be first function_2() { //do some stuff based on function_1()..}; // must be second function_3() { //do some st
function_1() { //do some stuff ..} ; // must be first
function_2() { //do some stuff based on function_1()..}; // must be second
function_3() { //do some stuff based on function_1() and function_2()..};; // must be third
它们都位于main()app函数下。您可以创建包装函数
bool execute()
{
return function_1() && function_2() && function_3();
}
这些函数将按顺序调用,如果任何函数出现故障,它将短路。假设函数返回一个表示成功/失败的
bool
,如果函数返回true
所有函数都成功完成,否则至少有一个函数失败。您可以尝试的一种方法是使用函数_1()
返回一个只有它才能构造的类型,然后将其用作函数2()的参数
现在,如果您第一次调用function\u 1
,则只能使用function\u 2
auto proof = function_1();
function_2(proof); // OK
function_2(created_by_function_1()); // Compilation error
我建议不要使用此选项:)为公共访问创建另一个函数,以确保以正确的顺序调用其他三个函数。为了防止这些函数在公共API中可见,可以将它们隐藏在未命名的命名空间中 在你的头上放
bool function_4();
在相应的转换单元中,创建一个未命名的名称空间,以防止其他人看到这些函数
namespace {
bool function_1() {
}
bool function_2() {
}
bool function_3() {
}
}
并定义函数_4
bool function_4() {
return function_1() &&
function_2() &&
function_3();
}
对函数进行排序的简单情况是生成一个由用户调用的函数,该函数完成所有三个子函数。然而,这并不总是有效的。在调用
function2
之前,用户可能需要在function1
之后进行一些处理。在这种情况下,您需要一些额外的上下文,例如
class Context
{
friend Function1, Function2, Function3;
enum State
{
f0, f1, f2, f3
} state;
public:
Context() { state = f0; }
~Context() { if (state != f3) { ... may need to do stuff... }
}
void Function1(Context &ctxt)
{
assert(ctxt.state == f0);
ctxt.state = f1;
...
}
void Function2(Context &ctxt)
{
assert(ctxt.state == f1);
ctxt.state = f2;
...
}
void Function3(Context &ctxt)
{
assert(ctxt.state == f2);
ctxt.state = f3;
...
}
int main()
{
Context c;
Function1(c);
...
Function2(c);
...
Function3(c);
// c will be destroyed and check that state is f3.
}
我想你有充分的理由不把这三个函数都打包成一个函数 在这种情况下,最简单的方法是管理所有三个功能之间共享的状态:
static int function_status=0; // shared status: nothing was called
function_1() {
if (status>0)
throw exception ("function_1 MUST be called first and only once");
status=1; // function_1 was called
...
}
function_2() {
if (status<1)
throw exception ("function_1 MUST be called before 2");
else if (status>2) // I suppose function 2 could be called several times
throw exception ("function_2 CANNOT be called after 3");
status = 2;
...
}
function_3() {
if (status<2)
throw exception ("function_2 MUST be called before 3");
else if (status==3)
throw exception ("function_3 CAN ONLY BE CALLED ONCE");
status = 3;
...
}
static int function\u status=0;//共享状态:未调用任何内容
函数_1(){
如果(状态>0)
抛出异常(“函数_1必须首先调用,并且只能调用一次”);
status=1;//调用了函数_1
...
}
函数_2(){
if(status2)//我想可以多次调用函数2
抛出异常(“3之后不能调用函数_2”);
状态=2;
...
}
函数_3(){
if(status)为什么不简单地提供一个可以通过API调用的第四个函数,并将另外三个函数移动到一个未命名的名称空间中呢?例如,Makefunction123(){function1();function2();function3();}
?这就是所谓的模板模式。看看你的声誉,我想如果你问这个问题,那是因为有一个合理的理由不把这三者都放在一个包装中,不是吗?加上1因为这不值得投反对票。匿名投票人又一次逍遥法外了。这个例子显示了预先确定fu顺序的糟糕方法编译器优化可以改变顺序,甚至可以跳过这些逻辑函数中的相同函数expressions@VolAnd编译器绝对不会更改此逻辑函数的顺序。标准规定必须按此顺序调用这些函数。如果编译器跳过任何函数,则如果前一个函数失败,则将是后一个函数ed,这是“短路行为”,这正是OP想要的。@Cyber抱歉,我不得不在回答时采用你的解决方案。我一直忽略了“短路行为”从OP的问题中指出。当然你是对的。@Cyber:请解释一下,为什么你如此确信任何在表达式func_1()&&func_2()&&func_1()&&func_3()
中具有任何优化级别的编译器都会调用func_1()
两次?如果你再往前走一步,你会得到一个流畅的api风格“myContext.function1().function2().function3()”@tofi9我想OP希望在调用他的函数之间有其他东西,否则为什么要单独公开它们(这就是为什么我认为他没有使用模板方法模式的原因)这里有一个陷阱:没有任何东西强迫客户机代码调用所有函数
static int function_status=0; // shared status: nothing was called
function_1() {
if (status>0)
throw exception ("function_1 MUST be called first and only once");
status=1; // function_1 was called
...
}
function_2() {
if (status<1)
throw exception ("function_1 MUST be called before 2");
else if (status>2) // I suppose function 2 could be called several times
throw exception ("function_2 CANNOT be called after 3");
status = 2;
...
}
function_3() {
if (status<2)
throw exception ("function_2 MUST be called before 3");
else if (status==3)
throw exception ("function_3 CAN ONLY BE CALLED ONCE");
status = 3;
...
}