问题
I was thinking of the following scenario:
class A {
private:
std::string id;
std::array<std::string, 128> data;
public:
A(const std::string& id) : id(id) {}
A(const A& other) : id(other.id), data(other.data) {}
virtual ~A(){}
//to override the intern data
A& operator=(const A& other) {
this->data = other.data;
return *this;
}
//to override the whole element
A& operator()(const A& other) {
this->id = other.id;
this->data = other.data;
return *this;
}
};
As you can see, my idea was to use operator= to override the internal data and operator() to override the whole element. I was inspired by the constructor which would allow A a(anOtherA);
to construct the element and I would like to override this for a re-construction. Now I don't now if this would be smart overloading this because it's actually the function call operator.
回答1:
Is overloading operator() for a reconstruction a good practice?
In short no, that isn't good practice. Such just obfuscates what is done under the hood.
Providing a setter for data
and use the code you provided in your overloaded operator()
for the implementation of the assignment operator=()
would provide the clearer and naturally expected semantics:
class A {
private:
std::string id;
std::array<std::string, 128> data;
public:
A(const std::string& id) : id(id) {}
A(const A& other) : id(other.id), data(other.data) {}
~A(){}
//to override the intern data
A& operator=(const A& other) {
id = other.id;
data = other.data;
return *this;
}
//to override the intern data
void setData(const A& other) {
data = other.data;
}
void setData(const std::array<std::string, 128>& data_) {
data = data_;
}
};
The semantics of the operator()
isn't that clearly defined (vs the operator=()
) beyond you can make a call of your class looking like a "normal" function call (which is mostly useful with templates taking your type as a parameter).
But I'd expect it more to do some action instead of changing the internal state of the class.
Regarding the style, instead of the set
/ get
prefixes for getter/setter functions I prefer what's done in the c++ standard library, (like e.g. with the std::ios_base::flags() property):
class A {
private:
// ...
std::array<std::string, 128> data_;
public:
const std::array<std::string, 128>& data() const {
return data_;
}
void data(const std::array<std::string, 128>& data) {
data_ = data;
}
// ...
};
回答2:
great answer from πάντα ῥεῖ so please upvote that answer, not this one.
As you write, and more importantly, read more c++ you will come to appreciate people who name methods and functions with natural, meaningful names.
For most of us, if we see code like this:
X x;
Y y;
x(y);
We would think, before even looking at the declarations of X
and Y
, that X
is some kind of function object (i.e. it does something) and Y
is some kind of data or state object - it likes having things done to it, or it supplies data or services.
As a side note, a Haskell programmer would naturally assume that Y
is also a function, but that's another story.
If your implementation of X::operator()(Y)
does not "do X-type stuff with or to a Y" then it is probably inappropriately named.
If Y
actually represents new state for X
, and X
intends to 'reset' itself using the data in Y
, then the method should probably be called... reset
:
X x;
Y y;
x.reset(y); //ok, this is telling a better story
With reasonable names we can tell a narrative with our code:
void processResults(XFactory& factory, std::istream& is) {
while(is) {
auto x = X::createFrom(factory);
x.collectNResults(is, 10);
auto a = x.takeAverage();
storeAverage(a);
x.reset(y);
}
}
Now even without looking up the definitions of the various classes I can get a sense of the general narrative. It's easier on the eye and I'm going to be able to hone in on the bits I need to see much more quickly than:
void processResults(XFactory& factory, std::istream& is) {
while(is) {
auto x = X(factory);
x(is, 10);
auto a = x();
x(averageStore);
x(y);
}
}
Which is what I'd have if I wrote every operation on an X in terms of a call operator which, much like corporate tax avoidance, is actually perfectly legal, but nevertheless happens to upset other people because they end up paying the price for your selfishness.
来源:https://stackoverflow.com/questions/41149115/is-overloading-operator-for-a-reconstruction-a-good-practice