为什么我们需要C ++中的虚函数?
我正在学习C ++,而我正在进入虚拟功能。
从我读过的(书中和在线中),虚函数是基类中的函数,您可以在派生类中重写。
但在本书的前面,在学习基本继承时,我能够在不使用virtual
情况下重写派生类中的基本函数。
那么我在这里错过了什么? 我知道虚拟功能还有更多,它似乎很重要,所以我想清楚它究竟是什么。 我在网上找不到直接的答案。
以下是我如何理解不仅是什么virtual
功能,而且为什么它们是必需的:
假设你有这两个类:
class Animal
{
public:
void eat() { std::cout << "I'm eating generic food."; }
};
class Cat : public Animal
{
public:
void eat() { std::cout << "I'm eating a rat."; }
};
在你的主要功能:
Animal *animal = new Animal;
Cat *cat = new Cat;
animal->eat(); // Outputs: "I'm eating generic food."
cat->eat(); // Outputs: "I'm eating a rat."
到目前为止很好,对吧? 动物吃普通食物,猫吃老鼠,全都没有virtual
。
现在让我们稍微改变它,以便通过中间函数调用eat()
(这个例子只是一个简单的函数):
// This can go at the top of the main.cpp file
void func(Animal *xyz) { xyz->eat(); }
现在我们的主要功能是:
Animal *animal = new Animal;
Cat *cat = new Cat;
func(animal); // Outputs: "I'm eating generic food."
func(cat); // Outputs: "I'm eating generic food."
呃哦...我们把一只猫传给func()
,但它不会吃老鼠。 如果你重载func()
所以它需要一个Cat*
? 如果你必须从动物中获得更多的动物,他们都需要自己的func()
。
解决的办法是让Animal
类的eat()
成为一个虚函数:
class Animal
{
public:
virtual void eat() { std::cout << "I'm eating generic food."; }
};
class Cat : public Animal
{
public:
void eat() { std::cout << "I'm eating a rat."; }
};
主要:
func(animal); // Outputs: "I'm eating generic food."
func(cat); // Outputs: "I'm eating a rat."
完成。
没有“虚拟”,你会得到“早期绑定”。 根据您调用的指针类型,在编译时决定使用哪种方法。
用“虚拟”你会得到“后期绑定”。 基于指向对象的类型 - 运行时决定使用哪个方法的实现 - 它最初的构造方式是什么。 这不一定基于指向该对象的指针的类型。
class Base
{
public:
void Method1 () { std::cout << "Base::Method1" << std::endl; }
virtual void Method2 () { std::cout << "Base::Method2" << std::endl; }
};
class Derived : public Base
{
public:
void Method1 () { std::cout << "Derived::Method1" << std::endl; }
void Method2 () { std::cout << "Derived::Method2" << std::endl; }
};
Base* obj = new Derived ();
// Note - constructed as Derived, but pointer stored as Base*
obj->Method1 (); // Prints "Base::Method1"
obj->Method2 (); // Prints "Derived::Method2"
编辑 - 看到这个问题。
另外 - 本教程将介绍C ++中的早期和晚期绑定。
您至少需要1级继承和downcast来展示它。 这是一个非常简单的例子:
class Animal
{
public:
// turn the following virtual modifier on/off to see what happens
//virtual
std::string Says() { return "?"; }
};
class Dog: public Animal
{
public: std::string Says() { return "Woof"; }
};
void test()
{
Dog* d = new Dog();
Animal* a = d; // refer to Dog instance with Animal pointer
cout << d->Says(); // always Woof
cout << a->Says(); // Woof or ?, depends on virtual
}
链接地址: http://www.djcxy.com/p/14099.html
上一篇: Why do we need virtual functions in C++?
下一篇: how to dynamically increase the stack size of a process