多态性:这种(潜在的密集)使用static_cast是致命的吗?
Polymorphism: is this (potentially intensive) use of static_cast a fatality?
这是上下文:Model
有一个(指向)Parameter
和一个output
。Model
和Parameter
是抽象类。我们使用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
当然会有一个例如 50Parameter
s 的向量,而不仅仅是一个,所以这意味着每次计算output
时 50static_cast
(或任何其他依赖于参数的操作)。这对我来说似乎不是一个好的做法,但我可能是错的。你看到设计有什么缺陷吗?
注意:我想过将Parameter
作为类模板,但这似乎不是一个有效的选项,因为当考虑不同类型的value
时,Parameter
的方法差异很大。在上面的简单示例中,value
的类型为int
,但在从Parameter
派生的另一个类中,它可以是用户定义的类型,例如 只有三个可能值R
、G
和B
的Color
,reinitialize()
与value = 1
非常不同。Parameter
中的虚拟getter()
会很好,但也不会起作用,因为重新定义中的返回类型冲突。
有几种方法可以使它更干净。 如果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
函数中,以避免多次使用它。
- 如何理解C++标准N3337中的expr.const.cast子句8
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- C++Cast运算符过载
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 收到错误"invalid use of non-static data member 'stu::n' "
- LNK1104:无法打开libpjproject-i386-Win32-vc14-Debug-Static.lib
- 我应该在 C++ 中何时/为什么使用 STATIC?
- 在VS2019项目中集成ImageMagick:x64-windows-static library
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- "static char __ = []() -> char"的含义
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- 无法在 DLL 中链接 SDL2-static.lib
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- C++线程"Call to non-static member function without an object argument"
- 出现这种错误的原因是什么"invalid use of non-static data member "
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- static是如何使用ClassA::m_variable处理所有类对象的
- 在[expr.static.cast]/4中,术语"一个可行函数"指的是什么