Избегать повторений кода в методах класса C ++?

Представление класса, который делает следующее

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! = 0, и тех, кто выдает ошибку, если mode! = 1. Можно ли как-то сгруппировать эти методы в две категории (категория A = метод, который выдает ошибку, если mode! = 0) и категория B для метода, который выдает ошибку, если mode! = 1)?

РЕДАКТИРОВАТЬГлядя на текущие ответы, я понимаю, как я формулирую вопрос, и проблема, вероятно, недостаточно ясна. Чего я хочу избежать, так это вызывать функцию в каждом методе класса. Пишем ли мы код в начале методов или помещаем этот код в функцию и вызываем эту функцию — это не проблема. Вопрос в том, сможем ли мы избежать всего этого вместе. Есть ли методика, которая поможет автоматически проверять, является ли вызов метода класса действительным в зависимости от некоторого контекста.

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

Я пытался выяснить, может ли какой-либо шаблон работать для этого, но ничего не смог найти. Это кажется мне невозможным, и я считаю, что единственный вариант — написать необходимый код. Может ли кто-нибудь предложить что-нибудь? Большое спасибо.

1

Решение

Просто добавьте приватные функции-члены:

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, конечно.

3

Другие решения

Помимо реализации проверки в специальном методе (отличное предложение), вы также можете рассмотреть возможность декомпозиции поведения в AClass на два отдельных класса или делегировать конкретную часть новой паре классов. Это кажется особенно уместным, если mode инвариантен для экземпляра (как в примере).

2

Ну, я думаю, простейшим решением было бы определение макроса или некоторой встроенной функции, например:

#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");
}

Таким образом, вы можете просто вызвать один из этих методов внутри функций, которые их требуют.

Но, скорее всего, есть более элегантный обходной путь для того, что вы хотите сделать.

0

После более подробного изучения проблемы кажется, что ближайший полезный ответ (Ник):

Попробуйте заглянуть в Аспектно-ориентированную разработку программного обеспечения en.wikipedia.org/wiki/Aspect-oriented_software_development — Ник

Страницу Википедии нелегко читать, и она не содержит пример C ++, поэтому сначала она остается очень абстрактной, но если вы ищете Аспектно-ориентированное программирование и C ++, вы найдете ссылки с примерами.

Идея, стоящая за этим (и это просто очень краткое резюме), состоит в том, чтобы найти способ добавления «сервисов» или «функциональных возможностей» к классу. Эти сервисы могут быть добавлены во время компиляции с помощью шаблонов. Это то, с чем я интуитивно экспериментировал, пытаясь решить мою проблему, и я рад видеть, что эта техника существует уже много лет.

Этот документ является хорошей ссылкой:

Аспектно-ориентированное программирование & C ++ Кристофер Диггинс, 1 августа 2004 г.

И я нашел эту ссылку с примером полезной для понимания концепции:

Реализация аспектов с использованием генеративного программирования от Calum Grant.

0
По вопросам рекламы [email protected]