我可以禁止在对象实例上调用静态方法吗?

问题描述 投票:15回答:5

我的课堂上有很多转换功能:

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

所以我想禁止从XXX调用对象,或者至少让他们做一些不同的事情。

有没有办法做到这一点?

c++ factory
5个回答
5
投票

他们真的需要成为班级成员吗?防止这种情况的明显方法是使它们具有自由功能。


3
投票

该标准实际上要求所有兼容的编译器都允许在9.4 [class.static] / 2中使用该语法:

X类的静态成员可以是使用qualified-id引用表达式X :: s;没有必要使用类成员访问语法(5.2.5)引用静态成员。一种静态成员可能使用类成员访问语法,在在这种情况下,对象表达式是已评估。

现在,您可以做一些事情来避免陷阱,但顺序不分先后

  • 将它们转换为不允许语法的自由功能
  • 改进命名约定:createFromXml以使其更明确地表明它是工厂方法
  • 将静态方法转换为将在对象中执行操作的具体方法,并提供将重用代码的外部方法工厂。

从设计的角度来看,第一个选项的优点是可以将序列化格式与类本身解耦。 Something(用一个更好的名字命名)代表具有属性和操作以及所有那些OO内容的对象。但在许多情况下,Something与可以序列化以以不同格式发送或存储的事实无关。

Something类的用户只想使用XML,甚至不需要知道您的对象可以序列化为Json。如果稍后向类添加数据库持久性选项,则Json或XML的用户都不会受到影响。


0
投票

改为修改您的设计。将您的静态方法拆分为单独的SomethingFactory类。这只是令人困惑。


0
投票

自c ++ 17起,您可以使用[[nodiscard]]属性:

class Something {
  public:

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

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

这不完全是您要的,但可能更好。


-1
投票

如何将您的静态成员设为私有?

如果您需要具有静态的成员函数,这可能是解决此问题的一种方法。

为什么具有静态成员函数?他们是否需要访问班级中的其他内容?如果没有,则可以使它们成为自由函数,这些自由函数不在带有Something的标头中,而是在单独的命名空间的另一个标头中。

© www.soinside.com 2019 - 2024. All rights reserved.