我在考虑以下情况:
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;
}
};
正如您所看到的,我的想法是使用operator =覆盖内部数据,使用operator()来覆盖整个元素。我受到构造函数的启发,它允许A a(anOtherA);
构造元素,我想重写它以进行重构。现在我现在不知道这是否会智能重载,因为它实际上是函数调用操作符。
答案 0 :(得分:3)
重载operator()重建是一种好习惯吗?
简而言之,这不是良好做法。这只是模糊了引擎盖下的内容。
为data
提供一个setter并使用您在重载operator()
中提供的代码来实现赋值operator=()
,这将提供更清晰且自然期望的语义:
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_;
}
};
operator()
的语义并没有明确定义(与operator=()
相比),除了你可以调用你的类看起来像“普通”函数调用(对于将类型作为参数的模板最常用)
但我希望更多的是做一些动作而不是改变类的内部状态。
关于样式,而不是getter / setter函数的set
/ get
前缀,我更喜欢在c ++标准库中完成的操作(例如,使用std::ios_base::flags()
属性):
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;
}
// ...
};
答案 1 :(得分:3)
在你写作时,更重要的是,阅读更多c ++,你会发现那些用自然,有意义的名字命名方法和功能的人。
对于我们大多数人来说,如果我们看到这样的代码:
X x;
Y y;
x(y);
在查看X
和Y
的声明之前,我们会认为X
是某种功能对象(即它有所作为)和Y
是某种数据或状态对象 - 它喜欢完成任务,或者提供数据或服务。
作为旁注,Haskell程序员自然会认为Y
也是一个函数,但这是另一个故事。
如果你的X::operator()(Y)
的实现没有“对Y做X类型的东西”那么它可能不恰当地命名。
如果Y
实际上代表X
的新状态,并且X
打算使用Y
中的数据“重置”自身,那么应该调用该方法。 .. reset
:
X x;
Y y;
x.reset(y); //ok, this is telling a better story
我们可以用合理的名字用我们的代码讲述一个叙述:
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);
}
}
现在,即使没有查阅各种类的定义,我也可以了解一般的叙述。它更容易在眼睛上,我将能够磨练我需要看到的位数比以下更快:
void processResults(XFactory& factory, std::istream& is) {
while(is) {
auto x = X(factory);
x(is, 10);
auto a = x();
x(averageStore);
x(y);
}
}
如果我根据呼叫运营商在X上编写每一项操作,这就是我所拥有的,这与公司避税一样,实际上是完全合法的,但却恰好打扰了其他人,因为他们最终支付了你自私的价格。