1

想象一个正在做以下事情的类

class AClass
{
    AClass() : mode(0) {}
    void a()
    {
        if (mode != 0) throw ("Error mode should be 0");
        // we pass the test, so now do something
        ...
        mode = 1;
    }
    void b()
    {
        if (mode != 1) throw("Error mode should be 1");
        // we pass the test, so now do something
        ...
    }
    int mode;
};

该类包含许多方法(容易超过 20 个),对于这些方法中的每一个,我们都需要检查 mode 的值,这显然是很多代码重复。此外,我们可以识别两类方法,如果 mode !=0 会抛出错误,如果 mode != 1 会抛出错误。是否有可能将这些方法分为两类(类别 A =如果 mode != 0) 抛出错误的方法和如果 mode != 1) 抛出错误的方法的类别 B?

编辑:查看当前答案,我意识到我提出问题的方式,问题可能还不够清楚。我要避免的是必须在类的每个方法中调用一个函数。无论我们是在方法的开头写代码还是把这段代码放在一个函数中并调用这个函数都不是问题。问题是我们是否可以一起避免这一切。是否有一种技术可以帮助根据某些上下文自动检查对类的方法的调用是否有效

AClass 实际上是我项目上下文中的一个 API。a()、b() 等是程序员可以调用的一些函数,如果她/他想使用 API,但是其中一些方法只能以某种精确的顺序调用。例如,您可以在代码中看到 a() 设置 mode = 1。因此程序员可以执行以下操作:

a(); // mode = 0 so it's good
b(); // mode = 1 so it's good

但是这段代码需要失败(它当然会编译,但在执行时我需要抛出一个错误,指出调用 b() 的上下文是错误的。

b(); // mode 0 so it won't work
a(); // it will compile but throw an exception

我试图看看是否有任何模式可以做到这一点,但根本找不到任何东西。这对我来说似乎是不可能的,我相信唯一的选择就是编写必要的代码。有人可以提出一些建议吗?非常感谢。

4

4 回答 4

3

只需添加私有成员函数:

void assert_mode_0() {
    assert_mode(0);
}

void assert_mode_1() {
    assert_mode(1);
}

void assert_mode(int m) {
    if (mode != m)
        throw msg[m];
}

当然,有一个合适的定义msg

于 2012-11-03T21:29:57.877 回答
2

除了在专用方法中实现检查(一个很好的建议),您还可以考虑将行为分解AClass为两个不同的类,或者将特定部分委托给一对新的类。mode如果实例不变(如示例中所示),这似乎特别合适。

于 2012-11-03T21:31:54.250 回答
0

在进一步研究了这个问题之后,似乎最有帮助的答案是(尼克):

尝试查看面向方面的软件开发 en.wikipedia.org/wiki/Aspect-oriented_software_development – Nick

Wikipedia 页面不易阅读,也没有提供 C++ 示例,因此起初它非常抽象,但如果您搜索 Aspect Oriented Programming and C++,您会找到示例链接。

它背后的想法(它只是一个非常快速的总结)是找到一种将“服务”或“功能”添加到类的方法。这些服务可以通过使用模板在编译时添加。这是我直观地尝试解决我的问题的尝试,我很高兴看到这种技术已经存在了很多年。

这个文档是一个很好的参考:

面向方面的编程和 C++,作者 Christopher Diggins,2004 年 8 月 1 日。

我发现这个带有示例的链接有助于理解这个概念:

Calum Grant 使用生成式编程实现方面。

于 2012-11-04T11:29:19.493 回答
0

好吧,我想最简单的解决方案是定义一个宏或一些像这样的内联函数:

#define checkErrorMode0(x) \
    if ((x) != 0) throw ("Error mode should be 0");
#define checkErrorMode1(x) \
    if ((x) != 1) throw ("Error mode should be 1");

// or, probably within your class
inline void checkErrorMode0(int x){
    if ( x != 0 ) throw ("Error mode should be 0");
}

inline void checkErrorMode1(int x){
    if ( x != 1 ) throw ("Error mode should be 1");
}

因此,您可以在需要它们的函数中简单地调用其中一种方法。

但很可能有一个更优雅的解决方法来解决您想要做的事情。

于 2012-11-03T21:18:15.667 回答