C++ 隐式构造函数转换后进行类型向上转换

标签 c++

我有一个程序,它有一个基类 Value 和多个继承自 Value 的子类(例如 IntValue)。这些类中的每一个都有接受一个或多个参数的构造函数。以下是示例代码,显示了我希望能够执行的操作:

#include <iostream>

class Value {
public:
  Value() {}
  virtual void print(std::ostream& os) const {}
};

class IntValue: public Value {
public:
  IntValue(int val): val_(val) {}
  void print(std::ostream& os) const override { os << val_; }
private:
  int val_;
};

class VariableValue: public Value {
public:
  VariableValue(const std::string& name): name_(name) {}
  void print(std::ostream& os) const override { os << name_; }
private:
  const std::string name_;
};

void emit_add(const Value& lhs, const Value& rhs, std::ostream& os) {
  lhs.print(os);
  os << " + ";
  rhs.print(os);
  os << std::endl;
}

template <class ValueType>
void emit_add(const ValueType& lhs, const ValueType& rhs, std::ostream &os) {
  lhs.print(os);
  os << " + ";
  rhs.print(os);
  os << std::endl;
}

int main() {
  // all these work                                                                              
  emit_add<IntValue>(12, 13, std::cout); // implicit constructors                                
  emit_add<VariableValue>(std::string("x"), std::string("y"), std::cout); // implicit constructo\
rs                                                                                               
  emit_add(VariableValue(std::string("x")), IntValue(1), std::cout); // implicit upcasting       

  // this doesn't                                                                                
  emit_add(std::string("x"), 13, std::cout); // implicit constor + implicit upcasting            

  return -1;
}

当我尝试使用 clang 9.1.0 进行编译时,出现以下错误:

test.cpp:47:3: error: no matching function for call to 'emit_add'
  emit_add(std::string("x"), 13, std::cout); // implicit constor + implicit upcasting
  ^~~~~~~~
test.cpp:25:6: note: candidate function not viable: no known conversion from 'std::string' (aka
      'basic_string<char, char_traits<char>, allocator<char> >') to 'const Value' for 1st
      argument
void emit_add(const Value& lhs, const Value& rhs, std::ostream& os) {
     ^
test.cpp:33:6: note: candidate template ignored: deduced conflicting types for parameter
      'ValueType' ('std::__1::basic_string<char>' vs. 'int')
void emit_add(const ValueType& lhs, const ValueType& rhs, std::ostream &os) {
     ^
1 error generated.

我的理解是,编译器无法调用 VariableValue 的隐式构造函数,然后将其向上转型为 Value 类型,但它显然可以单独执行这两项操作。

是否可以强制编译器执行此操作?

最佳答案

VariableValueValue(因为继承是一种“is a”关系),但 Value 不是 VariableValue (继承的“is a”关系是单向的)。

我想说的是,如果你有一个 VariableValue 对象,你可以轻松地沿着继承链向上获取一个 Value 对象(或者引用它)。但如果没有明确说明,您就不能走另一条路,从 Value 对象沿着继承链向下走。

您需要显式构造一个 VariableValue 对象并将其传递给您的函数:

emit_add(VariableValue(x), 13, std::cout);

关于C++ 隐式构造函数转换后进行类型向上转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52014168/

相关文章:

c++ - 如何在MFC Dialog中添加 Canvas ?

c++ - OpenCV findHomography 问题

c++ - 使用作为类成员的流写入文件

c++ - 为什么我收到错误 : interrupt service routine should have ‘unsigned long int’ as the second argument?

c++ - 如何只为一个类实现#pragma pointers_to_members()?

c++ - 有序元素的最佳容器

C++ 类排序

C++ 我可以使用什么代替 sleep() 函数?

C++17可选树,错误: invalid use of incomplete type

c++ - 引起问题的纹理