多态性:这种(可能是密集的)使用static_cast是致命的吗?

时间:2017-09-01 21:30:33

标签: c++ polymorphism abstract-class static-cast

以下是上下文:Model有一个(指针)ParameteroutputModelParameter是抽象类。我们使用Model*类型的指针来操作Model的各种派生(具体)类,它们指向Parameter的动态指向Parameter的各种派生(具体)类的实例

以下是类的简化版本。我知道new应该避免或者至少跟delete后面,但是我省略了非主题代码行(例如析构函数)。

// Abstract classes
class Parameter {
public:
    virtual void reinitialize() = 0;
};

class Model{
public:
    Model(Parameter *argt){ ptr_param = argt; }
    virtual void computeModelOutput() = 0;
    double output;
    Parameter *ptr_param;
};

// Concrete classes
class ACertainKindOfParameter : public Parameter{
public:
    ACertainKindOfParameter(int argt){ value = argt; }
    virtual void reinitialize(){ value = 1; }
    int value;
};

class ACertainKindOfModel : public Model{
public:
    ACertainKindOfModel(int argt) : Model(new ACertainKindOfParameter(argt)){}
    virtual void computeModelOutput(){
        output = 10.0 + (double)(static_cast<ACertainKindOfParameter*>(ptr_param)->value);
    }
};

int main(){
    ACertainKindOfModel myModel{5};
    Model *ptr_model = &myModel;
    ptr_model->computeModelOutput();
    std::cout << ptr_model->output << std::endl; // 15
}

在此代码中让我感到困扰的是ACertainKindOfModel无法直接访问value,因此我显然需要使用static_cast。真正的Model当然会有一个例如50 Parameter s,而不仅仅是一个,因此每次计算static_cast(或依赖参数的任何其他操作)时,这意味着50 output。对我来说这看起来不是一个好习惯,但我可能错了。你看到设计中有任何缺陷吗?

注意:我考虑过将Parameter作为一个类模板,但它似乎不是一个有效的选项,因为Parameter的方法在value的不同类型时有很大不同考虑。在上面的简单示例中,value的类型为int,但在另一个派生自Parameter的类中,它可以是用户定义的类型,例如只有三个可能值ColorRG以及B的{​​{1}}与reinitialize()非常不同。 value = 1中的虚拟getter()会很棒,但也不会有效,因为重新定义中的返回类型存在冲突。

1 个答案:

答案 0 :(得分:3)

有几种方法可以使它更清洁。如果Model不需要访问ptr_param,您可以将其从Model中删除,并将其存储在每个派生类中,并使用正确的类型。

或者您可以将static_cast封装在每个模型类中的getter函数中:

ACertainKindOfParameter *getParam() const { return static_cast<ACertainKindOfParameter *>(ptr_param); }

您可以将这两种技术结合起来。在派生模型类中定义参数,并使用协变返回类型以允许基类Model类访问。在Model内,声明一个getter:

virtual Parameter *getParam() const = 0;

然后,在每个模型中,声明一个协变覆盖:

virtual ACertainKindOfParameter *getParam() const override { return ptr_param; }

假设ptr_param在ACertainKindOfModel内声明。如果您不需要如上所述应用static_cast

或者您可以将static_cast的结果保存在compute函数中,以避免多次使用它。