我有一组类,它们都是从一个公共基类派生而来的。我想以多态方式使用这些类。接口定义了一组getter方法,它们的返回值在给定的派生类中是常量,但从一个派生类到另一个派生类不等。 e.g:
enum AVal
{
A_VAL_ONE,
A_VAL_TWO,
A_VAL_THREE
};
enum BVal
{
B_VAL_ONE,
B_VAL_TWO,
B_VAL_THREE
};
class Base
{
//...
virtual AVal getAVal() const = 0;
virtual BVal getBVal() const = 0;
//...
};
class One : public Base
{
//...
AVal getAVal() const { return A_VAL_ONE };
BVal getBVal() const { return B_VAL_ONE };
//...
};
class Two : public Base
{
//...
AVal getAVal() const { return A_VAL_TWO };
BVal getBVal() const { return B_VAL_TWO };
//...
};
等
这是一种常见的做事方式吗?如果性能是一个重要的考虑因素,我最好将属性拉出到外部结构中,例如:
struct Vals
{
AVal a_val;
VBal b_val;
};
在每个实例中存储Vals*
,并按如下方式重写Base
?
class Base
{
//...
public:
AVal getAVal() const { return _vals->a_val; };
BVal getBVal() const { return _vals->b_val; };
//...
private:
Vals* _vals;
};
额外的取消引用是否与vtable查找基本相同?这种情况的惯用语是什么?这些解决方案的两个 哑吗?非常感谢任何见解
答案 0 :(得分:1)
第一种方法看起来更清晰,并强制您覆盖这些方法(无论如何,在第一个孩子)。我认为虚拟呼叫的开销往往低于人们的预期。只有在您分析代码并且虚拟呼叫花费大量时间时,我才会尝试像您的第二种方法那样进行优化。
话虽如此,你想解决什么问题?有时像这样的类ID很有用,但有时候不同的接口抽象可以完成同样的事情,而根本没有这样的接口。
答案 1 :(得分:1)
我个人会实现一种GetTypeStats(),它返回一个(引用)结构,它包含所有派生的特定信息,或者像你在D3D中找到的QueryInterface。您还应该考虑此方案中的静态多态性。但是,如果您的类必须是运行时多态的,那么您无法真正消除虚函数调用。
答案 2 :(得分:0)
如果所有不同的是值并且它们在编译时被修复,那么你可以使它们成为模板参数:
template< AVal aval, BVal bval>
class Derived : public Base
{
AVal getAVal() const { return aval };
BVal getBVal() const { return bval };
};
typedef Derived<A_VAL_ONE, B_VAL_ONE> One;
typedef Derived<A_VAL_TWO, B_VAL_TWO> Two;
答案 3 :(得分:0)
当程序员想要避免使用dynamic_cast
时,这是为多态类型做穷人的dynamic_cast
的常用方法。在这些情况下,这是一种微观优化。与所有微优化一样,您需要在继续之前使用基于 need 的合理判断。如果分析器告诉您这样做而不是dynamic_cast
没有性能提升,那么使用dynamic_cast
可能会好得多。