在c++中使用dynamic_cast的替代方案

Alternative to using dynamic_cast in C++

本文关键字:cast 方案 dynamic c++      更新时间:2023-10-16

我有这些类:

class Field{
public:
    int X;
    void validate(){
        validator->validate(this);
    }
    void setValidator(Validator* v){
        validator = v;
    }
private:
    Validator* validator;
};
class DerivedField : public Field{
public:
    int Y;
}
class Validator {
public:
    virtual void validate(Field*); // do something with Field.X
};
class DerivedValidator : public Validator {
    virtual void validate(Field*); //do something with DerivedField.Y
};

我想这样做:

DerivedValidator* v = new DerivedValidator();
DerivedField* f = new DerivedFiled();
f->setValidator(v);
f->validate(); // Error, Validator::validate called instead of DerivedValidator::validate

既然它不工作,我能做些什么来避免这个:

class DerivedValidator{
    void validate(Field* f){
        DerivedField* dv = dynamic_cast<DerivedField*>(f);
        // do something with dv.Y
    }
};

谢谢。编辑:好吧,所有的"bug"现在都修复了。

首先,通过更改方法签名,您创建了一个将隐藏基类签名的新方法。你需要让DerivedValidator的validate()方法只接受一个Field*参数。

然后,一旦你在你的方法中添加了virtual关键字,当你传入一个DerivedField时,正确的方法应该被调用。

您仍然无法访问DerivedField的继承值,因为您没有告诉基类有关派生类的任何信息。例如,Field知道所有关于Validator的类型,但是不知道什么是DerivedValidator。无论您想在派生类中访问什么,都必须通过基类签名。

它不工作是好的,因为DerivedField不继承Field。如果你想破解,你可以使用c风格的强制转换。

与其为字段和验证器创建并行的类层次结构,不如这样设计:

class Field{
   public:
   int X;
   virtual bool validate(Validator* v){
      return (v->isValid(X));
   }
}
class DerivedField : public Field{
   public:
   int Y;
   virtual bool validate(Validator* v){
      return (v->isValid(X) && v->isValid(Y));
   }
}

每个派生的Validator类对于什么是有效的、什么是无效的都有不同的想法。

你的代码充满了小错误。首先,你的类没有派生自任何东西,我假设DerivedField继承自Field, DerivedValidator继承自Validator。其次,你需要写validator->validate,因为它是一个指针。第三,Field::validate没有参数,但你调用f->validate(v)。如果这些错误得到纠正,那么您唯一要做的就是使Validator::validate虚拟并使用您提出的解决方案(与dynamic_cast一起)。

您需要将Validator::validate()设为虚拟