[英]Calling overloaded constructor from constructor initialisation list
在下面的代码中,我的意图是基于将哪些参数传递给类material
的对象,调用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
}
同样失败了,因为出于类似编译时的原因,“三元运算符的结果必须始终是同一类型”,正如在类似问题中指出的那样(尽管在那里没有进行解释)。
现在,不雅的解决方案是根据kap
构造函数应接收的参数重载Matter
构造函数,但这是(1)非常不雅致的,尤其是因为Matter
构造函数需要许多变量并执行许多动作(所以很多代码将被复制,只是为了改变构造函数初始化列表的kap
部分),并且(2)如果另一个与Matter
使用的类也具有不同的构造函数,则这可能会失控:对于M个具有N个 c'tor的类,一个以N ^ M个组合结束...
有人提出建议或解决方法吗? 提前致谢!
如果opacity具有复制构造函数,则可以在初始化列表中完成此操作,避免使用默认构造函数,但要以复制为代价:
Matter::Matter(int i, double k, char * filename)
:kap( ( 0 < k ) ? opacity(k) : opacity( filename ) ) { ... }
您将不得不为opacity
添加默认构造函数(可能将mode设置为0
指示无效模式),并在构造函数主体中分配给kap
。
Matter::Matter(int i, double k, char * filename) {
if(k > 0)
kap = opacity(k);
else
kap = opacity(filename);
}
参数k
是运行时值。 无法使类型和重载结果取决于运行时值。
为了避免复制开销,并假设您具有C ++ 0x编译器,可以为opacity提供一个move构造函数,并让一个静态函数根据您的逻辑提供一个opacity
实例,并使用返回的临时opacity
初始化您的kap
成员。
您可能想要使kappa_array
类似auto_ptr<double>
指针。 尽管如果将此数据用于紧密循环,则与局部性和取消引用指针的成本相比,可移动性所节省的成本可能是可疑的。
opacity& get_opacity(double k, char * filename) {
if(k > 0)
return opacity(k);
else
return opacity(filename);
}
Matter::Mater(int i, double k, char * filename)
: kap(get_opacity(k, filename) {
//...
}
opacity::opacity(opacity&& other)
: mode(other.mode),
kap_const(other.kap_const),
kappa_array(std::move(kappa_array)) { }
请不要对此进行测试,我自己是移动语义和右值引用的新手...
您不能使用三元运算符来选择函数替代,因为运算符的结果只有一个类型。 如果不同的分支具有不同的类型,则它们将被强制转换为结果类型,否则将出现编译时错误。 请参阅http://en.wikipedia.org/wiki/%3F:#Result_type
真的不可能是其他任何方式。 类型需要在编译时由编译器知道,但是直到运行时才知道操作的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.