-1

我有这些课程:

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

谢谢你。

编辑:好的,现在所有的“错误”都已修复。

4

5 回答 5

3

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

然后,一旦您将 virtual 关键字添加到您的方法中,当您传入 DerivedField 时,应该调用正确的方法。

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

于 2011-08-08T12:13:40.527 回答
2

它不起作用很好,因为 DerivedField 不是从 Field 继承的。如果你想破解,你可以只使用 C 风格的演员表。

于 2011-08-08T12:12:12.613 回答
2

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

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 类对于什么是有效的什么是无效的都有不同的想法。

于 2011-08-08T12:15:04.030 回答
1

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

于 2011-08-08T12:18:45.977 回答
0

您需要使 Validator::validate() 虚拟。

于 2011-08-08T12:07:45.220 回答