从构造函数初始化列表中调用重载的构造函数

时间:2011-10-06 18:19:54

标签: c++ ternary-operator initializer-list constructor-overloading

在下面的代码中,我的目的是根据传递给类kap的对象的参数,为opacity(类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
 }

但这不起作用:

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
}

也失败了,因为“三元运算符的结果总是必须是编译时的原因”,正如similar question所指出的那样(虽然它们似乎没有解释,但似乎)。

现在,不优雅的解决方案是根据Matter构造函数应该接收的参数重载kap构造函数,但这是(1)非常不优雅,特别是因为{{1构造函数接受许多变量并执行许多操作(因此很多代码将被复制只是为了改变构造函数初始化列表的Matter部分),以及(2)如果有另一个,这可能会失控与kap一起使用的类也有不同的构造函数:对于带有 N c'tors的 M 类,一个以 N ^结尾 M 组合......

有人会有建议或解决方法吗?提前谢谢!

4 个答案:

答案 0 :(得分:4)

如果opacity具有复制构造函数,您可以在初始化列表中完成此操作,避免使用默认构造函数,但代价是复制:

  Matter::Matter(int i, double k, char * filename)
     :kap( ( 0 < k ) ? opacity(k) : opacity( filename ) ) { ... }

答案 1 :(得分:1)

您必须使用向opacity添加默认构造函数(可能将模式设置为0以指示无效模式)并在构造函数体中分配给kap。 / p>

Matter::Matter(int i, double k, char * filename) {
  if(k > 0)
    kap = opacity(k);
  else
    kap = opacity(filename);
}

参数k是运行时值。不可能使类型和重载结果取决于运行时值。

答案 2 :(得分:1)

为了避免复制开销,并假设你有一个C ++ 0x编译器,你可以给不透明度move constructor并使静态函数根据你的逻辑提供opacity的实例并初始化你的已返回临时kap的{​​{1}}成员。

你可能想让opacity指针像kappa_array一样。虽然如果这个数据用于紧密循环,但与地方成本和取消引用指针相比,可移动性的节省可能是可疑的。

auto_ptr<double>

请不要对此进行测试,我对移动语义和rvalue引用本身很新...

答案 3 :(得分:0)

您不能使用三元运算符来选择函数覆盖,因为运算符的结果只有一种类型。在不同分支具有不同类型的情况下,它们将被强制转换为结果类型,否则将出现编译时错误。见http://en.wikipedia.org/wiki/%3F:#Result_type

它实际上不是任何其他方式。编译器在编译时需要知道类型,但是直到运行时才能知道操作的结果。