我有一个班级Itch
,它是班级Scratch
的成员。我想在Scratch
构造函数中进行一些计算,并传递这些计算的结果来实例化Itch
对象。我最好的猜测是在下面,但这会返回垃圾:
#include <iostream>
class Itch {
public:
int N;
Itch(int n) {N = n;}
};
class Scratch {
private:
int N;
public:
Itch it;
Scratch(int n);
};
Scratch::Scratch(int n) : it(N) // here is where I want to use new data
{
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
}
int main() {
int n = 1;
Scratch sc(n);
std::cout << sc.it.N << "\n";
}
有没有一种标准方法可以做到这一点?
答案 0 :(得分:2)
初始化列表中的内容发生在构造函数代码中的内容之前。因此,您不能使用构造函数中的代码影响初始化列表中的任何内容。你有几个选择。
合理的做法是拥有Itch *
成员而不是Itch
,并在准备就绪时对其进行初始化,例如:
class Scratch {
...
Itch *it;
...
};
Scratch::Scratch(int n) : it(NULL)
{
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
it = new Itch(N); // <- now you have enough info to instantiate an Itch
}
除非你使用auto_ptr
,否则你必须记得在析构函数中清理:
Scratch::~Scratch () {
delete it;
}
另一种合理的方法是将n
传递给Itch
构造函数并让它在那里进行计算而不是Scratch
,甚至可以让Itch
确定{ {1}},例如:
N
另一种方法,即IMO有点奇怪,但在某些情况下仍然可能,例如,从class Itch {
private:
int N;
public:
Itch (int n);
int getN () const { return N; }
}
Itch::Itch (int n) {
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
}
Scratch::Scratch (int n) : it(n) {
// you can either remove Scratch::N altogether, or I suppose do:
N = it.getN();
// ... do whatever makes sense, try not to have redundant data.
// (also ask yourself if Scratch even *needs* to know N, or at
// least if it can just use it.getN() everywhere instead of
// keeping its own copy.)
}
计算N
的静态函数(成员与否),可以在初始化列表中使用,例如:
n
选择最干净,最易维护且易于阅读的代码。我个人更喜欢第一个static int doSillyThings (int n) {
int temp = 5;
temp += n + 45;
return temp - 1;
}
Scratch::Scratch(int n) : N(doSillyThings(n)), it(N)
{
}
选项,因为它具有逻辑意义且非常清楚:您需要进行初始化Itch *
所需的计算,然后进行初始化。
你应该考虑一下你的代码。如果Itch
Scratch
总是等于N
,那么真的是否需要it.N
s?
还有其他选项(包括完全重构您的代码,因此您不 拥有N
成员Itch
,或者您#39; t必须让Scratch
依赖于对it
构造函数参数进行的额外计算,但这实际上取决于具体情况),但希望这会激发您的灵感。
顺便说一下,你的代码返回垃圾的原因是因为Scratch
在你将它传递给N
构造函数时是垃圾。在您初始化它之前,它尚未初始化,并且Itch
尚未初始化it(N)
。