从构造函数初始化列表中调用重载构造函数
在下面的代码中,我的目的是根据传递给类 的对象的参数来调用
:kap
(类 opacity
)的两个重载构造函数之一材料
class opacity{
private:
int mode;
double kap_const;
double kappa_array[10][10];
public:
opacity(double constkap); // picking the constructor sets the mode
opacity(char* Datafile);
double value(double T, double P); // will return a constant or interpolate
};
opacity::opacity(double constkap):mode(1){
kap_const = constkap;
}
opacity::opacity(char* Datafile):mode(2){
// read file into kappa_array...
}
class Matter {
public:
Matter(int i, double k, char* filename); // many more values are actually passed
opacity kap;
int x; // dummy thing
// more variables, call some functions
};
Matter::Matter(int i, double k, char * filename)
:x(k>0? this->kap(x): this->kap(filename) ) {
// ... rest of initialisation
}
然而,这不起作用:
test.cpp: In constructor 'Matter::Matter(int, double, char*)':
test.cpp:32:21: error: no match for call to '(opacity) (void*&)'
test.cpp:32:42: error: no match for call to '(opacity) (char*&)'
test.cpp:32:44: error: no matching function for call to 'opacity::opacity()'
test.cpp:32:44: note: candidates are:
test.cpp:20:1: note: opacity::opacity(char*)
test.cpp:20:1: note: candidate expects 1 argument, 0 provided
test.cpp:16:1: note: opacity::opacity(double)
test.cpp:16:1: note: candidate expects 1 argument, 0 provided
test.cpp:4:7: note: opacity::opacity(const opacity&)
test.cpp:4:7: note: candidate expects 1 argument, 0 provided
我尝试的第一件事
Matter::Matter(int i, double k, char * filename)
:kap(k>0? k: filename) { // use k<0 as a flag to read from filename
// ... rest of initialisation
}
也失败了,因为出于编译时原因,“三元运算符的结果始终必须是相同的类型”,如 <一个href="https://stackoverflow.com/questions/4693629/ternary-operator?answertab=votes#tab-top">类似问题(尽管似乎没有在那里解释)。
现在,不优雅的解决方案是根据 kap
构造函数应接收的参数重载 Matter
构造函数,但这 (1) 非常不优雅,特别是因为Matter
构造函数接受许多变量并执行许多操作(因此会重复很多代码,只是为了改变构造函数初始化列表的 kap
部分),并且 (2)如果还有另一个可能会失控与 Matter
一起使用的类也具有不同的构造函数:对于具有 N 个 C'tors 的 M 个类,最终会得到 N em>^ M 组合...
有人有建议或解决方法吗?提前致谢!
In the code below, my intent is to call one of two overloaded constructors for the kap
(class opacity
) based on what arguments are passed to the object of class material
:
class opacity{
private:
int mode;
double kap_const;
double kappa_array[10][10];
public:
opacity(double constkap); // picking the constructor sets the mode
opacity(char* Datafile);
double value(double T, double P); // will return a constant or interpolate
};
opacity::opacity(double constkap):mode(1){
kap_const = constkap;
}
opacity::opacity(char* Datafile):mode(2){
// read file into kappa_array...
}
class Matter {
public:
Matter(int i, double k, char* filename); // many more values are actually passed
opacity kap;
int x; // dummy thing
// more variables, call some functions
};
Matter::Matter(int i, double k, char * filename)
:x(k>0? this->kap(x): this->kap(filename) ) {
// ... rest of initialisation
}
This is however not working:
test.cpp: In constructor 'Matter::Matter(int, double, char*)':
test.cpp:32:21: error: no match for call to '(opacity) (void*&)'
test.cpp:32:42: error: no match for call to '(opacity) (char*&)'
test.cpp:32:44: error: no matching function for call to 'opacity::opacity()'
test.cpp:32:44: note: candidates are:
test.cpp:20:1: note: opacity::opacity(char*)
test.cpp:20:1: note: candidate expects 1 argument, 0 provided
test.cpp:16:1: note: opacity::opacity(double)
test.cpp:16:1: note: candidate expects 1 argument, 0 provided
test.cpp:4:7: note: opacity::opacity(const opacity&)
test.cpp:4:7: note: candidate expects 1 argument, 0 provided
The first thing I had tried,
Matter::Matter(int i, double k, char * filename)
:kap(k>0? k: filename) { // use k<0 as a flag to read from filename
// ... rest of initialisation
}
also failed, because "the result of a ternary operator always has to be the same type" for compile-time reasons, as pointed out in a similar question (although they were not explained there, it seems).
Now, the inelegant solution would be to also overload the Matter
constructor based on the arguments that the kap
constructor should receive, but this is (1) very inelegant, especially since the Matter
constructor takes many variables and performs many actions (so a lot of code would be duplicated just to vary the kap
part of the constructor initialisation list), and (2) this can get out of hand if there is another class used with Matter
that also has different constructors: for M classes with N c'tors, one ends up with N^ M combinations...
Would someone have a suggestion or a work-around? Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您不能使用三元运算符来选择函数覆盖,因为该运算符的结果只有单一类型。在不同分支具有不同类型的情况下,它们将被强制为结果类型,否则将出现编译时错误。请参阅http://en.wikipedia.org/wiki/%3F:#Result_type
确实不可能有其他方式。编译器需要在编译时知道类型,但直到运行时才知道操作的结果。
You can't use a ternary operator to select function overrides because the result of the operator only has a single type. In the case where the different branches have different types, they will be coerced to the result type or there will be a compile time error. See http://en.wikipedia.org/wiki/%3F:#Result_type
It couldn't really be any other way. Types need to be known by the compiler at compile time, but the result of the operation isn't known until run time.
如果 opacity 有复制构造函数,您可以在初始化列表中完成此操作,避免使用默认构造函数,但代价是复制:
If opacity has a copy constructor, you could accomplish this in the initialization list, avoiding a default constructor, but at the cost of a copy:
您将不得不忍受向
opacity
添加默认构造函数(这可能将模式设置为0
以指示无效模式)并分配给kap
在构造函数主体中。参数
k
是运行时值。不可能使类型和重载结果依赖于运行时值。You will have to live with adding a default constructor to
opacity
(which perhaps sets mode to0
to indicate an invalid mode) and assign tokap
in the constructor body.The parameter
k
is a runtime value. It is not possible to make types and overloading result depend on runtime values.为了避免复制开销,并假设您有 C++0x 编译器,您可以为不透明度指定 移动构造函数并让静态函数根据您的逻辑提供
opacity
实例,并使用返回的临时opacity
初始化您的kap
成员>。您可能希望将
kappa_array
设为一些指针,例如auto_ptr
。尽管如果在紧密循环中使用此数据,则与局部性和取消引用指针的成本相比,可移动性带来的节省可能是值得怀疑的。请不要在这方面测试我,我自己对移动语义和右值引用还很陌生......
To obviate copy overhead, and assuming you have a C++0x compiler, you could give opacity a move constructor and have a static function provide an instance of
opacity
based on your logic and initialize yourkap
member with the returned temporaryopacity
.You'd probably want to make
kappa_array
some pointer likeauto_ptr<double>
. Though if this data is used in a tight-loop, the savings from moveability may be dubious compared to the cost of locality and dereferencing the pointer.Please don't test me on this, I'm pretty new with move semantics and rvalue references myself...