大佬教程收集整理的这篇文章主要介绍了C动态对象类比较,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
class Expr { public: virtual bool compare(const Expr *other) const = 0; };
例如,NumExpr和AddExpr是两个具体的子类,分别用于表示文字整数表达式和二进制加法表达式.每个比较方法所做的第一件事是使用dynamic_cast来确保另一个表达式具有相同的类型:
class NumExpr : public Expr { int num; public: NumExpr(int n) : num(n) {} bool compare(const Expr *other) const { const NumExpr *e = dynamic_cast<const NumExpr*>(other); if (e == 0) return false; return num == e->num; } }; class AddExpr : public Expr { Expr *left,*right; public: AddExpr(Expr *l,Expr *r) : left(l),right(r) {} bool compare(const Expr *other) const { const AddExpr *e = dynamic_cast<const AddExpr*>(other); if (e == 0) return false; return left->compare(e->left) && right->compare(e->right); } };
当我使用dynamic_cast时,我总觉得我做错了什么 –
是否有更合适的方法来执行对象之间的动态比较
不使用dynamic_cast?
使用visitor design pattern并不能解决对RTTI的需求(据我所知). “表达式访问者”的抽象基类可能如下所示:
class NumExpr; class AddExpr; class ExprVisitor { public: virtual void visit(NumExpr *E) {}; // "do nothing" default virtual void visit(AddExpr *E) {}; };
class Expr { public: virtual void accept(ExprVisitor& v) = 0; };
具体的表达式子类然后使用double dispatch来调用适当的访问方法:
class NumExpr : public Expr { public: int num; NumExpr(int n) : num(n) {} virtual void accept(ExprVisitor& v) { v.visit(this); }; }; class AddExpr : public Expr { public: Expr *left,*right; AddExpr(Expr *l,right(r) {} virtual void accept(ExprVisitor& v) { v.visit(this); }; };
当我们最终使用这种机制进行表达式比较时,我们仍然需要使用RTTI(据我所知);例如,以下是用于比较表达式的示例访问者类:
class ExprCompareVisitor : public ExprVisitor { Expr *expr; bool result; public: ExprCompareVisitor(Expr *E) : expr(E),result(false) {} bool getResult() const {return result;} virtual void visit(NumExpr *E) { NumExpr *other = dynamic_cast<NumExpr *>(expr); result = other != 0 && other->num == e->num; } virtual void visit(AddExpr *E) { AddExpr *other = dynamic_cast<AddExpr *>(expr); if (other == 0) return; ExprCompareVisitor vleft(other->left); e->left->accept(vleft); if (!vleft.getResult()) return; ExprCompareVisitor vright(other->right); e->right->accept(vright); result = vright.getResult(); } };
注意我们仍在使用RTTI(dynamic_cast就是这种情况).
如果我们真的希望避免RTTI,我们可以“自己动手”创建独特的常量来识别每个具体的表达风格:
enum ExprFlavor { NUM_EXPR,ADD_EXPR }; class Expr { public: const ExprFlavor flavor; Expr(ExprFlavor f) : flavor(f) {} ... };
每种具体类型都会适当地设置它:
class NumExpr : public Expr { public: int num; NumExpr(int n) : Expr(NUM_EXPR),num(n) {} ... }; class AddExpr : public Expr { public: Expr *left,Expr *r) : Expr(ADD_EXPR),left(l),right(r) {} ... };
然后我们可以使用static_cast和flavor字段来避免RTTI:
class ExprCompareVisitor : public ExprVisitor { Expr *expr; bool result; public: ExprCompareVisitor(Expr *E) : expr(E),result(false) {} bool getResult() const {return result;} virtual void visit(NumExpr *E) { result = expr->flavor == NUM_EXPR && static_cast<NumExpr *>(expr)->num == e->num; } ... };
这个解决方案似乎只是复制了RTTI在幕后所做的事情.
它看起来像这样:
class Expr { public: virtual bool compare(const Expr *other) const = 0; virtual bool compare(const NumExpr *other) const { return false; } virtual bool compare(const AddExpr *other) const {return false;} }; class NumExpr : public Expr { int num; public: explicit NumExpr(int n) : num(n) {} bool compare(const Expr *other) const { return other->compare(this); } bool compare(const NumExpr *other) const { return num == other->num; } };
以上是大佬教程为你收集整理的C动态对象类比较全部内容,希望文章能够帮你解决C动态对象类比较所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。