在C ++中,基类和派生类是反映现实生活层次结构的概念的流行示例。
除此之外,还有一些很小但非常有用的概念,这些概念经过特殊设计,以使代码保持简单,并使C ++程序员的生活更轻松。
One such concept is C++ 虚拟 functions.
In this tutorial, we will understand 虚拟 functions concept in detail through C++ code examples.
没有虚拟功能的示例代码
首先,让我们使用以下简单的C ++示例代码’t use 虚拟 function.
#包括<iostream> class A { public: const char* fetchClassName() { return "A"; } }; class B: public A { public: const char* fetchClassName() { return "B"; } }; int main(void) { B obj_b; A &obj_a = obj_b; std::cout << obj_a.fetchClassName() << "\n"; }
这是上面程序的输出:
A
如果您遵守写在‘main()’函数中,类A的对象是指类B的对象。但是,当函数‘fetchClassName()’通过类A的对象进行调用,则调用了类A的相应功能。
现在,如果我们想要那样‘fetchClassName()’在相同情况下将被称为B类?
好吧,这就是虚拟功能概念出现的地方。在进一步探讨这个概念之前,让我们先看一下虚拟函数如何解决我们的问题。
如果您不熟悉C ++, 你好世界C ++程序 和 C ++构造函数和析构函数 可能会让您快速入门。
具有虚拟功能的示例代码
这是相同的代码,但这次是函数‘fetchClassName()’ is made 虚拟 :
#包括<iostream> class A { public: 虚拟 const char* fetchClassName() { return "A"; } }; class B: public A { public: 虚拟 const char* fetchClassName() { return "B"; } }; int main(void) { B obj_b; A &obj_a = obj_b; std::cout << obj_a.fetchClassName() << "\n"; }
因此,您可以看到该功能‘fetchClassName()’通过添加关键字将其虚拟化‘virtual’ in it’s declaration.
这是上面程序的输出。将函数设为虚拟后,程序将生成正确的预期输出。
B
现在让我们了解为什么要创建函数‘fetchClassName()’影响了输出。
- 在第一个示例中,对象‘obj_a’指向课程的基础部分‘A’ in class ‘B’. So, when ‘obj_a.fetchClassName()’被称为,类的相应功能‘A’ was called.
- 现在,当功能‘fetchClassName()’被虚拟化,然后‘virrtual’关键字确保程序搜索了派生版本。它在B类中找到,因此被称为B类功能。
So this means that through 虚拟 functions, 上e can access the functions with similar prototype in the derived class.
下一个问题是,我们是否需要使派生类函数起作用‘fetchhClassName()’ 虚拟? Well, let’s从中省略虚拟关键字’s prototype :
#包括<iostream> class A { public: 虚拟 const char* fetchClassName() { return "A"; } }; class B: public A { public: const char* fetchClassName() { return "B"; } }; int main(void) { B obj_b; A &obj_a = obj_b; std::cout << obj_a.fetchClassName() << "\n"; }
这是这种情况下的输出:
B
因此,我们看到virtual关键字仅在class函数中是必需的‘A’因为这足以使程序在派生类中寻找相似的功能‘B’。如果要上课‘C’这本来可以从‘B’那么在那种情况下‘fetchClassName()’ of class ‘C’会被称为。
这是一个类的例子‘C’ is also involved :
#包括<iostream> class A { public: 虚拟 const char* fetchClassName() { return "A"; } }; class B: public A { public: const char* fetchClassName() { return "B"; } }; class C: public B { public: const char* fetchClassName() { return "C"; } }; int main(void) { C obj_c; A &obj_a = obj_c; std::cout << obj_a.fetchClassName() << "\n"; }
这是上面程序的输出。如您所见,由于Class中函数的虚拟性质‘A’,类的功能相似‘C’ was executed.
C
照顾功能原型
请注意,为了正常工作,虚拟功能及其所有功能’派生类中的对应对象应具有相同的原型。如果原型不匹配,则可能无法按预期进行。
这是一个例子:
#包括<iostream> class A { public: 虚拟 const char* fetchClassName() { return "A"; } }; class B: public A { public: const char* fetchClassName() { return "B"; } }; class C: public B { public: const char* fetchClassName(int a) { return "C"; } }; int main(void) { C obj_c; A &obj_a = obj_c; std::cout << obj_a.fetchClassName() << "\n"; }
您可以在Class中看到该函数的原型‘C’与上面的示例代码不同。
以下是上述程序的输出:
B
输出确认Class中的函数‘C’由于原型不同,因此不被认为是应聘者。
此规则有一个例外:所有具有指针或对派生类的引用作为返回类型的重写函数都将被视为具有完全相同原型的普通函数。
如果您喜欢这篇文章,您可能还会喜欢..
![]() |
![]() |
![]() |
![]() |
如果不这样做,对虚拟功能的描述不是很有用’不要说为什么要实现虚拟功能。不幸的是’可以在此主题上写整本书,而不是全部介绍。
C ++具有虚函数,因此开发人员可以在基类中描述一种行为(通过定义虚函数),然后在几个派生类的每一个中提供行为的几个实例(通过实现虚函数)。在示例中,指定的行为是“fetch the class name”,各种实现方式是;返回“A”, return “B”, etc.
通常基类不’t完全实现行为,因为它表示行为的一种,而不是实际的行为。我们可能会建立一个班级家庭来实施儿童教育’在其上带有字母的构建基块(以激励将它们命名为A,B和C;所有示例都是la脚,对不起)。然后,该基类可能称为LetterBlock,并且可能具有虚函数GetLetter(),GetSound()和GetPicture()。派生类A将实现GetLetter()返回“A”,GetPicture()返回飞机的图片,而GetSound()将产生一个“Whoosh!”声音。 B类将返回船的图像,并发出舷外发动机的声音。每个派生类以不同的方式实现一种行为(发出声音,产生图片)。
这种行为称为多态的,因为它是同一类型的行为,但是它采取许多特定的形式。
It’将基类视为定义一个接口(类家族要提供的一组行为)也很有意义;以及派生为接口的实现。
看,你可以写整本书…