C ++派生类覆盖返回类型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C ++派生类覆盖返回类型相关的知识,希望对你有一定的参考价值。
我想我下面的例子将解释我想要做的事情。我知道我不能覆盖eval()函数的返回类型,除非它们是协变量,所以显然我做错了。我的问题:我如何拥有一个多态基类和派生类,可以用不同的方式评估自己?
#include <iostream>
class Node {
public:
virtual void eval() = 0;
};
class IntNode: public Node {
public:
IntNode() { val = 0; }
IntNode(int i) { val = i; }
int eval() { return val; }
private:
int val;
};
class FloatNode: public Node {
public:
FloatNode() { val = 0; }
FloatNode(float i) { val = i; }
float eval() { return val; }
private:
float val;
};
int main() {
Node *a = new IntNode(5);
Node *b = new FloatNode(2.3);
std::cout << a->eval() << std::endl;
std::cout << b->eval() << std::endl;
return 0;
}
编辑:已解决
谢谢大家的建议。我找到了实现自己最终目标的方法。最后我想要一个多态符号表。我用了一些你的想法来实现这一点。最大的突破是做到了“双面”加功能。要添加两个Vars,第一个要求另一个使用第一个值添加另一个Vars:
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
class Var {
public:
virtual void print() = 0;
virtual Var *plus(int i) = 0;
virtual Var *plus(float f) = 0;
virtual Var *plus(Var *other) = 0;
};
class IntVar: public Var {
public:
// constructors
IntVar();
IntVar(int i);
void print();
// operations
Var *plus(int i);
Var *plus(float f);
Var *plus(Var *other);
private:
int val;
};
class FloatVar: public Var {
public:
// constructors
FloatVar();
FloatVar(float f);
void print();
// operations
Var *plus(int i);
Var *plus(float f);
Var *plus(Var *other);
private:
float val;
};
// constructors
IntVar::IntVar() { val = 0; }
IntVar::IntVar(int i) { val = i; }
void IntVar::print() { cout << "" << val << endl; }
// operations
Var *IntVar::plus(int i) { return new IntVar(i+val); }
Var *IntVar::plus(float f) { return new FloatVar(f+val); }
Var *IntVar::plus(Var *other) { return other->plus(val); }
// constructors
FloatVar::FloatVar() { val = 0; }
FloatVar::FloatVar(float f) { val = f; }
void FloatVar::print() { cout << "" << val << endl; }
// operations
Var *FloatVar::plus(int i) { return new FloatVar(i+val); }
Var *FloatVar::plus(float f) { return new FloatVar(f+val); }
Var *FloatVar::plus(Var *other) { return other->plus(val); }
int main() {
unordered_map<string, Var *> symbol_table;
symbol_table["a"] = new IntVar(5);
symbol_table["b"] = new FloatVar(2.3);
symbol_table["c"] = symbol_table["a"]->plus(symbol_table["b"]);
symbol_table["a"]->print();
symbol_table["b"]->print();
symbol_table["c"]->print();
return 0;
}
答案
你不能。
表达式的静态类型不能取决于对象的动态类型。举个例子:
auto f(Node& n) { return n.eval(); }
什么是f
?
您可以使用std::variant
解决您的问题,但这意味着基类知道子类可以返回的所有类型。这确实是一个设计问题,你应该修复它。
另一答案
一个简单的答案是你不能。 C ++中的覆盖必须返回与原始函数相同的类型。
但是,你可以通过一些技巧获得更复杂的答案。其中一个技巧是使用类型擦除的返回值,例如,通过std::any
- 更多关于它在https://en.cppreference.com/w/cpp/utility/any上的用法
使用std::any
,函数可以返回他们想要的任何值,但它将被类型擦除 - 因此调用者必须知道如何处理此返回值...在某种意义上,这严重限制了此解决方案的适用范围。但是,也有这个地方。
以上是关于C ++派生类覆盖返回类型的主要内容,如果未能解决你的问题,请参考以下文章