Могу ли я запретить вызов статических методов в экземпляре объекта?

У меня есть класс с множеством функций преобразования:

class Something {
  public:

    string toXml();
    string toJson();
    ...

    static Something fromXml(string);  // factory
    static Something fromJson(string); // factory
    ...
};

Поскольку статические функции можно вызвать в экземпляре, легко написать такой код:

Something sss;

... initializing sss ...

string xml1 = sss.toXml();
sss.fromXml(xml1); // does nothing
string xml2 = sss.toXml();
assert(xml1 == xml2); // always true

Поэтому я хочу запретить вызов fromXXX на объекты или по крайней мере, сделать их чем-то другим.

Есть ли способ сделать это?

Ответы

Ответ 1

Действительно ли они должны быть членами класса? Очевидный способ предотвратить это - сделать их свободными функциями.

Ответ 2

Стандарт фактически требует, чтобы все совместимые компиляторы разрешали этот синтаксис в 9.4 [class.static]/2:

Статический член s класса X может быть упоминается с использованием идентификатора с квалификацией выражение X:: s; это не обязательно использовать синтаксис доступа к члену класса (5.2.5) для обозначения статического члена. статический член, возможно, ссылается на использование синтаксис доступа к члену класса, в в этом случае объект-выражение оценены.

Теперь есть некоторые вещи, которые вы можете сделать, чтобы избежать ловушки, ни в каком конкретном порядке

  • Преобразуйте их в бесплатные функции, запрещающие синтаксис
  • Улучшите соглашение об именах: createFromXml, чтобы сделать более явным, что это метод factory
  • Преобразовать статический метод в конкретный метод, который будет выполнять операцию в объекте, и предоставить внешний метод factory, который будет повторно использовать код.

С точки зрения дизайна, первый вариант имеет преимущество в том, что он унифицирует сериализованные форматы из самого класса. Something (по лучшему имени), представляет объект со свойствами и операциями и все эти вещи OO. Но во многих случаях Something не имеет отношения к тому, что его можно сериализовать для отправки или хранения в разных форматах.

Пользователи вашего класса Something, которые хотят работать только с XML, не должны даже знать, что ваш объект может быть сериализован для Json. Ни один из пользователей Json или XML не должен быть затронут, если позже вы добавите параметр сохранения базы данных в класс.

Ответ 3

Вместо этого измените свой дизайн. Разделите свои статические методы на отдельный класс SomethingFactory. Это просто сбивает с толку.

Ответ 4

Как сделать ваши статические члены частными?

Если вам нужны статические функции-члены, это может быть способ решить эту проблему.

Почему у вас есть статическая функция-член? Нужен ли им доступ к чему-то еще в классе? Если нет, то вы можете сделать их свободными функциями, которые не входят в заголовок с Something, но в другом заголовке в отдельном пространстве имен.