Ya, в основном вы используете операторы печати в своей функции как способ возврата информации. Вы не должны этого делать. Печать - это не то же самое, что и оператор возврата. Если вы просто хотите, чтобы ваша функция давала ваш ответ без них, просто введите jiskya (2, 3). Вы увидите, что функция выбрасывает, потому что у вас есть инструкции печати в функции. Если вместо этого вы набрали «возврат» в своей функции, это не даст вам ничего, кроме «печати», предшествующей вызову функции.
Как уже было сказано, NVI - это прозаичная идиома, связанная с категорией языков. Этому способствует и Herb Sutter, потому что он помогает заключать контракты:
Однако реализация может существенно различаться, например, другой пример реализации NVI состоит в том, чтобы объединить его с Pimpl:
class FooImpl;
class Foo
{
public:
enum type { Type1, Type2 };
Foo(type t, int i, int j);
int GetResult() const;
private:
FooImpl* mImpl;
};
И для реализации:
struct FooImpl
{
virtual ~FooImpl();
virtual int GetResult() const;
};
class FooType1: public FooImpl
{
public:
FooType1(int i, int j);
virtual int GetResult() const;
private:
/// ...
};
Я всегда обнаружил, что он передал точку лучше , Вы поняли это?
Главное, что virtual
является деталью реализации. И разоблачение деталей реализации в интерфейсе - плохая идея, потому что вы можете изменить их.
Кроме того, детали реализации, как правило, несовместимы с бинарной совместимостью. Например, добавление нового метода virtual
в класс может изменить макет виртуальной таблицы (обычная техника реализации) и, таким образом, botch совместимость двоичных файлов. На gcc вам нужно убедиться, что вы добавите последний (среди виртуальных), если хотите сохранить совместимость.
Используя комбинацию NVI + Pimpl выше, нет virtual
вообще ( даже не закрытый) в классе выставлен. Макет памяти совместим с обратной связью. Мы достигли бинарной совместимости.
Здесь мы используем сразу несколько шаблонов: