使用虚函数与dynamic_cast
using virtual function vs dynamic_cast
与其使用虚函数,不如使用类似的东西:
void BaseClass::functionName () { // BaseClass already has virtual functions
// some LONG code true for all derived classes of BaseClass
// ...
if (typeid (*this) == typeid (DerivedClass1))
// use functions of DerivedClass1 on dynamic_cast<DerivedClass1*>(this)
else if (typeid (*this) == typeid (DerivedClass2))
// use functions of DerivedClass2 on dynamic_cast<DerivedClass2*>(this)
// some LONG code true for all derived classes of BaseClass
// ...
}
只是我觉得将虚函数用于上述内容不是一个好主意,因为它只是专门用于派生类的一小部分。 然后,需要对所有派生类一遍又一遍地使用用于所有派生类的长代码(建议为此使用帮助程序函数)。 当然,我已经测试了我的方法并且它有效(我想没有性能损失),但我想知道这是否是有问题的做法。如果 if-else-if 部分在函数中多次使用怎么办?
如果所有派生类的通用代码都是相对短的,那么最好使用虚函数,对吧?
为什么不这样做:
void BaseClass::functionName () {
// some LONG code true for all derived classes of BaseClass
// ...
this->some_protected_virtual_member_function();
// some LONG code true for all derived classes of BaseClass
// ...
}
因此,公共部分不会重复,并且该行为仍然可以轻松地在子类中具有扩展,而无需向父类添加另一个if
除非类具有虚函数,否则您的代码根本无法工作。C++ 只提供有限的反射:typeid(DerivedClass1)==typeid(DerivedClass2) 如果没有虚函数。上面的代码也可能比简单地访问虚拟函数慢:你会得到每种类型的新分支,而不是恒定的时间指针查找。
但是,上述代码的最大问题是它松散了多态性和封装性。使用代码必须知道 DerivedClass1 和 DerivedClass2 需要做什么。它需要了解 DerivedClass1 和 DerivedClass2 中的结构。此外,所有代码都堆积在一个地方,使此函数可能有数百行。
我认为您正在这里寻找模板方法模式: 只需使用您现有的非虚拟函数,并让它仅为具体类之间不同的一小部分代码调用虚函数。它的优点是看起来更漂亮。
void BaseClass::functionName () {
// some LONG code true for all derived classes of BaseClass
// ...
functionName_impl(); // Will be virtual (private or protected) and overriden in each child class to do the right work.
// some LONG code true for all derived classes of BaseClass
// ...
}
这是模板方法模式的退化情况:
class Base {
public:
void templated() {
// do some stuff
this->hook1();
// other stuff
if (/*cond*/) { this->hook2(); }
size_t acc = 0;
for (Stuff const& s: /*...*/) { acc += this->hook3(s); }
// other stuff
}
private:
virtual void hook1() {}
virtual void hook2() {}
virtual size_t hook3(Stuff const&) { return 0; }
}; // class Base
然后Derived
类可以自定义钩子的行为。
警告:这本质上是非常严格的,因为templated
方法不是virtual
;这既是这种模式的优点,也是问题,这很好,因为如果您需要更改templated
方法,那么它是在一个地方定义的,如果提供的钩子不足以自定义行为,那就很烦人了。
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 在成员dynamic_bitset上使用 boost::from_block_range 时出错,但在本地dynamic
- C++类中的二维"dynamic"数组?
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- protobuf in C++ with dynamic binding for google::protobuf::M
- 警告的原因是什么:"when type is in parentheses, array cannot have dynamic size"?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- CUDA 错误:"dynamic initialization is not supported for __device__, __constant__ and __shared__ variabl
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- 如何修复'The procedure entry point SDL_RWclose could not be located in the dynamic link library'
- Shared_ptr cast vs static_cast speed
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- "The ordinal 344 could not be located in the dynamic link library"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- Dynamic Cast C++ Fail
- dynamic-cast-c++dynamic_cast错误处理