И константная, и неконстантная версия одной и той же функции — анти-паттерн?

Недавно я проверил огромное количество унаследованного кода C ++ и нашел то, чего никогда не видел в производственном коде C ++:

class Foo
{
public:
void Bar()
{
std::cout << "Hello from Bar()!" << std::endl;
}

void Bar() const
{
const_cast<Foo*>(this)->Bar();
}
};

Это огромный анти-паттерн? Я имею в виду, что функция является константной или неконстантной, какой смысл предоставлять две версии? Является ли это своего рода «обманом константности», который позволяет вызывать константные функции в таких ситуациях:

void InvokeBar(const Foo& foo)
{
// oh boy! I really need to invoke a non-const function on a const reference!
foo.Bar();
}

3

Решение

Нет не всегда.

Есть законное использование этого шаблона. Например, предположим, что вы пишете коллекцию, а код для извлечения элемента довольно сложный (например, хеш-таблица). Вы не хотите дублировать весь код, но вы также хотите, чтобы ваша коллекция могла использоваться как постоянная, так и неконстантная.

Итак, вы можете сделать что-то вроде этого:

struct HashTable {
...

const Value &get(Key key) const {
... complex code for retrieving the key
}

Value &get(Key key) {
return const_cast<Value &>(
static_cast<const HashTable *>(this)->get(key)
);
}
};

Здесь const_cast<> на самом деле это не ложь. Поскольку ваша функция неconstвы знаете, что он может быть вызван, только если объект, на который указывает this также неконстантен. Следовательно, отбрасывание константности действительно.

(конечно, аналогично этой ситуации, вы можете назватьconst метод, отбрасывая const-есть const экземпляр, но в этот момент это пользователь вашего класса, который уже ввел неопределенное поведение, так что вы покрыты, пока ваш класс используется правильно.)

7

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector