使用虚函数创建实例,为什么?

时间:2016-04-27 19:06:42

标签: c++ function virtual

我对虚函数或方法有疑问。我在stackoverflow link to post上发现了一个非常好的帖子,解释了虚函数为何以及如何工作。我理解虚拟功能现在如何工作,但我仍然不明白为什么你需要它们。如果你查看链接和提供的示例,他会创建一个这样的实例:

A *a1 = new B;
a1->show();

但是如果你想使用B中的函数,你为什么要创建这样的实例呢?为什么不这样做:

B b1 = new B;
b1->show();

当我想使用B引用时,为什么我应该使用A指针?

我希望你们明白我不会得到什么,并且可以向我解释。

3 个答案:

答案 0 :(得分:2)

扩展代码库以包含从C派生的类A

现在添加一个函数display_A,定义为:

void display_A(A* aPtr)
{
   a->show();
}

您可以将该函数与B的实例以及C的实例一起使用。

B* bPtr = new B;
C* cPtr = new C;

display_A(bPtr);
display_A(cPtr);

此处,B*C*会在调用A*之前自动转换为display_A。无论aPtr->show()指向display_A还是aPtrB中的C都有效。这是创建virtual函数的真正动机。

使用目的

A *a1 = new B;
a1->show();

表示即使指针的类型为B::show(),如果指针指向的是A*对象,也会调用B

答案 1 :(得分:2)

这是 Polymorphism 的一个很好的例子。

简而言之,多态性允许两种不同的类型(类)为不同的底层实现提供相同的接口。

不要使用A和B作为示例,而应考虑两个类 Motorcycle Car 摩托车汽车都可以驱动,对吗?你驾驶这两辆车的方式是完全不同的。这两个类都应该提供 drive()方法,尽管它们的实现方式不同。

class Vehicle {
    public:
        virtual void drive() = 0;
}

class Car : public Vehicle {
    public:
        void drive() {
            // Driving to work, however a car does that.
        };
}

class Motorcycle : public Vehicle {
    public:
        void drive() {
            // Driving to work, however a motorcycle does that.
        };
}
Vehicle *car = new Car;
Vehicle *motorcycle = new Motorcycle;

// We can both be driven, so we share the same interface.
car->drive();
motorcycle->drive();

将对象传递给函数时,这可能特别有用。你有一个功能,实现了工作。只要你以某种方式被驱使,你真的不在乎如何你的工作。

void driveToWork(Vehicle *vehicle) {
    vehicle->drive();
}

driveToWork(new Car);

// It's Tuesday, your car broke down!
// As long as we use a Vehicle to get to work, all is well.
driveToWork(new Motorcycle);

答案 2 :(得分:1)

最重要的是,当你调用一个虚函数时,它会执行它能够执​​行该函数的最多派生形式

class Message
{
     virtual void buildMessage();
}

class ShutdownMessage : public Message
{
     virtual void buildMessage() { /* Do a thing. */ }
}

class StartupMessage : public Message
{
     virtual void buildMessage() { /* Do a totally different thing. */ }
}

void prepareMessage(Message *M)
{
    M->buildMessage();
}

现在你可以这样称呼:

prepareMessage(myMsg);

在任何消息上,它将调用相应的buildMessage函数。