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

Calling overloaded constructor from constructor initialisation list

本文关键字:构造函数 重载 调用 初始化 列表      更新时间:2023-10-16

在下面的代码中,我的意图是根据传递给类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
}

也失败了,因为由于编译时的原因,"三元操作符的结果总是必须是相同的类型",正如在一个类似的问题中指出的那样(尽管那里似乎没有解释)。

现在,不雅的解决方案是还超载Matter构造函数基于kap构造函数应该接受的争论,但这是(1)非常不雅的,尤其是Matter构造函数变量和执行许多操作(所以很多代码是重复的只是改变kap构造函数初始化列表的一部分),和(2)这可能失控如果有另一个类用于Matter也有不同的构造函数:对于具有N c'变量的M类,最终得到N^ M组合…

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

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

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

您将不得不为opacity添加默认构造函数(可能将模式设置为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

不可能有其他的方式。类型需要在编译时被编译器知道,但是操作的结果直到运行时才知道。