use*_*715 2 c++ operator-overloading
我得到了以下代码:
class FibHeapNode
{
//...
// These all have trivial implementation
virtual void operator =(FibHeapNode& RHS);
virtual int operator ==(FibHeapNode& RHS);
virtual int operator <(FibHeapNode& RHS);
};
class Event : public FibHeapNode
{
// These have nontrivial implementation
virtual void operator=(FibHeapNode& RHS);
virtual int operator==(FibHeapNode& RHS);
virtual int operator<(FibHeapNode& RHS);
};
class FibHeap
{
//...
int DecreaseKey(FibHeapNode *theNode, FibHeapNode& NewKey)
{
FibHeapNode *theParent;
// Some code
if (theParent != NULL && *theNode < *theParent)
{
//...
}
//...
return 1;
}
};
Run Code Online (Sandbox Code Playgroud)
FibHeap的大部分实现都是类似的:FibhepeNode指针被解除引用然后进行比较.
为什么这段代码有效?(或者它有多少?)我认为virtual
这里的s没有效果:因为*theNode和*theParent不是指针或引用类型,所以不会发生动态调度,无论写入什么,都会调用FibHeapNode :: operator <事件.
你必须对动态调度有点困惑.
人们常说"动态调度仅在您通过指针或通过引用进行调用时才会发生".从形式上讲,这种说法完全是虚假和误导的.
C++中的动态调度总是在您调用虚函数时发生,只有一个例外:当您使用目标函数的完全限定名时,将禁用动态调度.例如:
some_pointer->SomeClass::some_function(); // fully-qualified name
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,即使some_function
是虚函数,也将静态调度调用.从语言的角度来看,没有其他方法可以避免动态调度,即在所有其他情况下,所有对虚函数的调用都是动态调度的.您使用的是:指针,引用,直接对象 - 无关紧要,调度仍然是动态的.你从以下函数调用函数:来自构造函数/析构函数或来自其他地方 - 无关紧要,调度仍然是动态的.我再说一遍:这就是C++语言本身的观点.这就是"抽象C++机器"的工作原理.
What happens in practice though, is that in many cases the dynamic dispatch can be replaced with static dispatch, because the compiler knows the dynamic type of the object in advance, at the compile-time and, consequently, knows the target of the dispatch. In such cases it makes more sense to call the target function directly, instead of going through the costlier dynamic dispatch mechanism. Yet, this is nothing else than just an optimization. Some people, unfortunately, mistake that optimization for language-mandated behavior, coming up with such meaningless statements as "dynamic dispatch occurs only when you make a call through a pointer or through a reference".
在您的特定情况下,调度是动态的.因为在您的情况下编译器不知道所涉及对象的动态类型,所以它无法将其优化为静态调度,这就是您的代码"按预期工作"的原因.
PS预测我上面提到的可能的问题:从构造函数/析构函数调用的动态调度受到对象的当前动态类型的限制,这就是为什么在简单的情况下编译器可以(并且容易)优化它们进入静态调度.这就是另一个流行的都市传奇的原因,它表明构造函数/析构函数的虚拟调用是静态解决的.实际上,在一般情况下,它们是动态解决的,因为它们应该(再次观察对象的当前动态类型).