c++ - 虚函数指针混淆

标签 c++ pointers inheritance polymorphism virtual

众所周知,我们可以使用指向基类的指针来访问派生类中基类的重写虚函数。

下面是一个这样的例子。

#include <iostream>

class shape {
public:
    virtual void draw() {
    std::cout << "calling shape::draw()\n";
    }
};

class square : public shape {
public:
    virtual void draw() {
        std::cout << "calling square::draw()\n";
    }
    int area() {
        return width*width;
    }
    square(int w) {
        width = w;
    }
    square() {
        width = 0;
    }

protected:
    int width;
};

class rect : public square {
public:
    virtual void draw() {
        std::cout << "calling rect::draw()\n";
    }

    int area() {
        return width*height;
    }
    rect(int h, int w) {
        height = h;
        width = w;
    }
protected:
    int height;
};

int main() {
    /*
    shape* pshape[3] = {
        new shape,
        new square(2),
        new rect(2, 3)
        };

    for (int i = 0; i<3; i++){
        pshape[i]->draw();
    }
    */
    square* psquare = new rect(2, 3);
    psquare->draw();
    system("pause");
    return 0;
}

pshape[i] 指针可以轻松访问虚函数draw()。 现在是令人困惑的部分。 “方形”类是“矩形”类的基类。因此,如果有一个 square* 指针,它可以访问“rect”类(square* psquare = new rect(2, 3);) 的 draw() 函数,并且输出是:

calling rect::draw()
Press any key to continue . . .

现在,如果我从 square::draw() 定义中删除“virtual”关键字,它的代码仍然可以编译并且输出是相同的:

calling rect::draw()
Press any key to continue . . .

最后,如果我从基本函数中删除“virtual”,psquare->draw() 的输出是:

calling square::draw()
Press any key to continue . . .

这让我很困惑。这里到底发生了什么?

  1. 因为 squarerect 类的父类,square 应该有它的 draw() 函数是虚函数为了让 rect 覆盖它。但它仍在编译并提供与虚拟化时相同的输出。
  2. 因为shape是所有类的基类,去掉shape中draw()的virtual关键字应该会出错。但这并没有发生,它正在编译并在调用 psquare->draw() 时给出另一个输出 calling square::draw()

我可能在很多事情上都是错的。请更正错误并告诉我这里到底发生了什么。

最佳答案

如果一个函数在基类中声明为虚函数,那么它在所有派生类中自动为虚函数,就像您在其中放置一个virtual 关键字一样。参见 C++ "virtual" keyword for functions in derived classes. Is it necessary? .

如果函数不是虚函数,那么调用哪个版本将取决于调用它的指针类型。调用父类中的成员函数绝对没问题,因为派生类的每个实例都是其每个父类的实例。所以那里没有错误。

关于c++ - 虚函数指针混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42605614/

相关文章:

c++ - 理解 Malloc 实现

c++ - 指针和引用传递 C++

c++ - 从函数 C++ 返回数组

c++ - 模板继承和基本成员变量

c# - 成员的继承和可见性

c++ - 在 C++ 中编译时间类型确定

c++ - 双重自由或腐败(!prev)c++ opencv

c++ - 如何正确地将 float 与 int 相乘并获得仅受有效数字影响的结果?

c++ - std::algorithm::sort 的比较器?

c - 带有指向函数指针的结构