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

发布于 2024-12-08 22:37:10 字数 2305 浏览 1 评论 0原文

在下面的代码中,我的目的是根据传递给类 的对象的参数来调用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心凉 2024-12-15 22:37:11

您不能使用三元运算符来选择函数覆盖,因为该运算符的结果只有单一类型。在不同分支具有不同类型的情况下,它们将被强制为结果类型,否则将出现编译时错误。请参阅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.

岁月苍老的讽刺 2024-12-15 22:37:10

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

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

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:

  Matter::Matter(int i, double k, char * filename)
     :kap( ( 0 < k ) ? opacity(k) : opacity( filename ) ) { ... }
叹倦 2024-12-15 22:37:10

您将不得不忍受向 opacity 添加默认构造函数(这可能将模式设置为 0 以指示无效模式)并分配给 kap在构造函数主体中。

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

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

You will have to live with adding a default constructor to opacity (which perhaps sets mode to 0 to indicate an invalid mode) and assign to kap in the constructor body.

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

The parameter k is a runtime value. It is not possible to make types and overloading result depend on runtime values.

秋意浓 2024-12-15 22:37:10

为了避免复制开销,并假设您有 C++0x 编译器,您可以为不透明度指定 移动构造函数并让静态函数根据您的逻辑提供opacity实例,并使用返回的临时opacity初始化您的kap成员>。

您可能希望将 kappa_array 设为一些指针,例如 auto_ptr。尽管如果在紧密循环中使用此数据,则与局部性和取消引用指针的成本相比,可移动性带来的节省可能是值得怀疑的。

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)) { }

请不要在这方面测试我,我自己对移动语义和右值引用还很陌生......

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 your kap member with the returned temporary opacity.

You'd probably want to make kappa_array some pointer like auto_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.

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)) { }

Please don't test me on this, I'm pretty new with move semantics and rvalue references myself...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文