我有一个程序,该程序的基类Value
具有从IntValue
继承的多个子类(例如Value
)。这些类中的每一个都有接受一个或多个参数的构造函数。这是示例代码,显示了我想做的事情:
#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
类型,但显然可以单独完成这两个操作。是否可以强制编译器执行此操作?
最佳答案
VariableValue
是Value
(因为继承是"is"关系),但是Value
不是VariableValue
(继承是“is”关系是单向的)。
我要说的是,如果您有VariableValue
对象,则可以轻松地在继承链中向上获取Value
对象(或它的引用)。但是,如果不明确说明,您就不能沿相反的方向从Value
对象继承链。
您需要显式构造一个VariableValue
对象并将其传递给您的函数:
emit_add(VariableValue(x), 13, std::cout);