我正在回顾一些 c++ 概念(几年前我用过它(,函数重载的概念现在对我来说很有意义,尤其是对于我去年在 powershell 编程经验中遇到的一些场景。 例如,现在我可以轻松地向某人解释它对于软件重构非常有用,使代码可读性更容易等......
我不明白的是函数覆盖的用法/好处。它有哪些好的用例?从研究中,我刚刚读到它用于为父类中的子类函数具有不同的行为,但是,您不能只将子类中的函数命名为其他名称,并直接以这种方式调用它而不用担心父类函数?
您不能只将子类中的函数命名为其他名称,然后直接以这种方式调用它而不用担心父类函数吗?
不,因为不可能有运行时动态调度,这是多态性的全部基础。
(动态调度是用C++(和大多数其他语言(使用基于vtable(virtual
(的调用实现的(。其他语言如Objective-C和Smalltalk使用消息传递范式。用 C 语言编写的程序必须自己实现 vtable-call-call 或消息传递(例如通过使用函数指针(。
考虑这个伪代码[3]的例子:
class AnyCat {
abstract void MakeSound();
}
class HouseCat extends AnyCat {
override void MakeSound() {
Console.WriteLine( "Meow" );
}
}
class Lion extends AnyCat {
override void MakeSound() {
Console.WriteLine( "Roar" );
}
}
static void Main() {
AnyCat cat = GetRandomNumber() % 2 == 0 ? new HouseCat() : new Lion();
cat.MakeSound(); // <-- this is a vtable/virtual-call
}
由于cat
运行时可以是HouseCat
的,也可以是Lion
的,所以编译器(以及程序员!(不能使用"静态调用"[4]来MakeSound
。
[3] 我没有使用 C++ 的class
声明语法,因为它太冗长了,而且C++目前不需要使用override
说明符,所以对于初学者来说,当方法声明会导致 vtable 调用或只是阴影时,它并不明显。
[4] 在这种情况下,"静态调用"在一般意义上意味着"静态编译"或"在编译时固定"(例如"静态类型"(。它与 OOP 编程语言中的static
关键字或static
-方法无关(尽管有趣的事实:对static
方法的所有调用都是静态调用(。
如果子类中的函数需要与基类中提供的函数具有不同的功能,则可以重写该函数。一个例子(非常简洁,参见其他编程语言(:
struct Person
{
virtual ~Person() = default; // make this a polymorphic type
void bonus()
{
throw "Not a chance.";
}
};
struct Boss : Person
{
void bonus() // overrides the base class function
{
// open banking payment system
// pay the bonus
// close the banking payment system
}
};
这种经典的功能覆盖确实已经过时了,正在被组合型模式所取代。在这种情况下bonus()
可以是Person
中实现的纯虚函数,在每个子类中实现。