gpt4 book ai didi

C++ - 使指向父类(super class)的指针与函数中的子类参数匹配

转载 作者:行者123 更新时间:2023-11-30 05:27:32 66 4
gpt4 key购买 nike

我在询问之前进行了搜索,但没有找到任何解决我的问题的方法。

我想让一个指向父类(super class)的指针(实际上总是指代其中一个子类)与函数中的子类参数(指针或常量引用)相匹配。

上下文:用 C++ 创建一个“高级”计算器。

让我向您详细介绍本期中使用的类:

首先我们有文字:

class Literal {};
class IntegerLiteral : public Literal {};
class RealLiteral : public Literal {};
class RationalLiteral : public Literal {};
//....

我们有一个堆栈,用于通过存储 Literal 对象的地址来保存它们

// If st is instance of stack then :
st.top(); // returns a Literal*

我们有 Operator 对象,它们将通过拆分正确数量的 Literal*(取决于运算符的元数)与堆栈交互,将运算符应用于 Literal* 对象并最终堆叠结果。

class Operator {
int n; // operator arity
public:
virtual void executeOperator(stack *st) = 0; //
};

Operator 子类之一(例如):

class PlusOperator : public Operator {
public:
virtual void execute(StackUTComputer *st) override {
Literal* arg1 = st->top();
Literal* arg2 = st->top();
Literal* result = applyOperator(arg1, arg2);
st->pop(); st->pop();
st->push(result);
}

Literal* execute(IntegerLiteral* a, IntegerLiteral* b) {
return new IntegerLiteral(a->getValue() + b->getValue());
}

Literal* execute(IntegerLiteral* a, RealLiteral* b) {
return new RealLiteral(a->getValue() + b->getValue());
}


Literal* execute(IntegerLiteral* a, RationalLiteral* b) {
return new RationalLiteral(
a->getValue() + (a->getValue()*b->getDenominator()),
b->getDenominator()
);
}

// ...
};

我在这里的目的(通过重载函数 applyOperator)是“神奇地”让计算机知道调用哪个函数取决于运算符拆栈的真实类型的 Literal(类 Literal 是抽象的:堆栈将始终包含具体的 Literal 子类)。

但它并没有按照我想要的方式工作。我的意思是调用 applyOperator(arg1, arg2)(arg1arg2 是 Literal*)是无效的,因为没有函数与签名匹配。

我知道我以另一种通常使用的方式使用 c++ 多态性 int(即为采用父类(super class)参数的函数提供子类参数)。

我不知道如何改变我的架构以正确使用多态性,也许有一些语法上有用的解决方案可以让我的想法发挥作用。

无论哪种方式,我都感谢您的帮助!

拉斐尔。

最佳答案

有一种方法可以按预期使用多态性(无需 dynamic_cast):

#include <iostream>
#include <memory>
#include <string>

struct IntegerLiteral;
struct RealLiteral;

struct Literal {
virtual void add(const Literal &) = 0;
virtual void add(const IntegerLiteral &) = 0;
virtual void add(const RealLiteral &) = 0;

virtual void add_to(Literal &) const = 0;
virtual void add_to(IntegerLiteral &) const = 0;
virtual void add_to(RealLiteral &) const = 0;
virtual std::ostream &print(std::ostream &os) const = 0;
virtual ~Literal() = default;
};

std::ostream &operator<<(std::ostream &os, const Literal &l) {
return l.print(os);
}

struct IntegerLiteral : Literal {
IntegerLiteral(int i)
: i(i) {}
int i = 0;
void add(const Literal &other) override {
//now we know one operand is an IntegerLiteral and can pass on that information to the other Literal
other.add_to(*this);
}
void add(const IntegerLiteral &other) override {
i += other.i;
}
void add(const RealLiteral &other) override;
void add_to(Literal &other) const override {
other.add(*this);
}
void add_to(IntegerLiteral &other) const override {
other.i += i;
}
void add_to(RealLiteral &other) const override;
std::ostream &print(std::ostream &os) const override {
return os << i;
}
};

struct RealLiteral : Literal {
RealLiteral(double d)
: d(d) {}
double d = 0;
void add(const Literal &other) override {
other.add_to(*this);
}
void add(const IntegerLiteral &other) override {
d += other.i;
}
void add(const RealLiteral &other) override {
d += other.d;
}
void add_to(Literal &other) const override {
other.add(*this);
}
void add_to(IntegerLiteral &other) const override {
//now we know both operands and can do the calculation
other.i += d;
}
void add_to(RealLiteral &other) const override {
other.d += d;
}
std::ostream &print(std::ostream &os) const override {
return os << d;
}
};

void IntegerLiteral::add(const RealLiteral &other) {
i += other.d;
}

void IntegerLiteral::add_to(RealLiteral &other) const {
other.d += i;
}

int main() {
std::unique_ptr<Literal> l1 = std::make_unique<RealLiteral>(3.14);
std::unique_ptr<Literal> l2 = std::make_unique<IntegerLiteral>(42);
l1->add(*l2);
std::cout << *l1 << '\n';
}

DEMO

你需要大量的代码来完成这项工作,而且你添加的每个 Literal 都会以二次方的方式变得更糟,而每个运算符都会使它变得更糟两倍。此外,如果您忘记覆盖一个函数,您可能会在运行时遇到无限循环和堆栈溢出。
一种更好的方法(更易于编写且运行速度更快)是只对所有内容使用 doubleBigNum,而不用担心多态性。

关于C++ - 使指向父类(super class)的指针与函数中的子类参数匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37237358/

66 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com