简体   繁体   中英

Alternative to using dynamic_cast in C++

I have these classes:

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
};

I want to do this:

DerivedValidator* v = new DerivedValidator();
DerivedField* f = new DerivedFiled();
f->setValidator(v);

f->validate(); // Error, Validator::validate called instead of DerivedValidator::validate

Since It doesnt work, what can I do to avoid this:

class DerivedValidator{
    void validate(Field* f){
        DerivedField* dv = dynamic_cast<DerivedField*>(f);

        // do something with dv.Y
    }
};

Thank you.

Edit: Ok, all 'bugs' fixed now.

First, by changing the method signature, you've created a new method that will hide the base class's. You need to have DerivedValidator's validate() method take a Field* parameter only.

Then, once you've added the virtual keyword to your methods, when you pass a DerivedField in, the correct method should be called.

You still won't be able to access the inherited values of DerivedField as you haven't told the base class anything about the derived class. ie, Field knows all about Validator types, but has no clue what a DerivedValidator is. Whatever you want to access in the derived class has to go via the base class signature.

It's good that it doesn't work, since DerivedField doesn't inherit from Field. If you want to hack, you can just use C-style casts.

Rather than creating a parallel class hierarchy for fields and validators, you might be better off with a design something like this:

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));
   }
}

Each of your derived Validator classes can have different ideas of what is valid and what isn't.

You code is full of small errors. First, your classes son't derive from anything, I assume DerivedField inherits from Field and DerivedValidator from Validator . Second, you need to write validator->validate , as it's a pointer. Third, Field::validate has no argument but you call f->validate(v ). If these errors are corrected, then the only thing you got to do is make Validator::validate virtual and use your proposed solution (with the dynamic_cast ).

您需要将Validator :: validate()虚拟化。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM