Can I forbid calling static methods on object instance?
I have class with lots of conversion functions:
class Something {
public:
string toXml();
string toJson();
...
static Something fromXml(string); // factory
static Something fromJson(string); // factory
...
};
Because static functions can be called o开发者_JAVA百科n instance, it is easy to write code like this:
Something sss;
... initializing sss ...
string xml1 = sss.toXml();
sss.fromXml(xml1); // does nothing
string xml2 = sss.toXml();
assert(xml1 == xml2); // always true
So I want to forbid calling fromXXX on objects, or at least make them do something different.
Is there a way to do this?
Do they really need to be class members? The obvious way to prevent this is to make them free functions.
The standard actually requires all compliant compilers to allow that syntax in 9.4 [class.static]/2:
A static member s of class X may be referred to using the qualified-id expression X::s; it is not necessary to use the class member access syntax (5.2.5) to refer to a static member. A static member maybe referred to using the class member access syntax, in which case the object-expression is evaluated.
Now, there are some things you can do to avoid the pitfall, in no particular order
- Convert them into free-functions disallowing the syntax
- Improve the naming convention:
createFromXml
to make more explicit that it is a factory method - Convert the static method into a concrete method that will perform the operation in the object, and provide an external method factory that will reuse the code.
From a design point of view, the first option has the advantage of un-coupling the serialized formats from the class itself. Something
(by a better name), represents an object with properties and operations and all those OO things. But in many cases Something
is unrelated to the fact that it can be serialized for sending or storage in different formats.
Users of your Something
class that only want to work with XML don't need to even know that your object can be serialized to Json. Neither users of Json or XML should be affected if you later add a database persistence option to the class.
Since c++17 you may use the [[nodiscard]]
attribute:
class Something {
public:
...
static [[nodiscard]] Something fromXml(string); // factory
static [[nodiscard]] Something fromJson(string); // factory
...
};
This wasn't exactly what you're asking for, but possibly better.
Revise your design instead. Split your static methods into a separate SomethingFactory class. This is just confusing.
How about making your static members private?
If you need to have member functions that are static this may be a way to solve this.
Why do you have static member function? Do they need access to something else in the class? If not, then you could make them free functions that are not in the header with Something
, but in another header in a separate namespace.
精彩评论