C ++方法覆盖

时间:2012-01-30 14:16:39

标签: c++ override

关于C ++中方法覆盖的this文章中的维基百科示例是否正确?

请参阅下面的代码,我在其中提到了评论// INCORRECT

稍微混淆了C ++和运行时多态性。这个演员应该怎么做?

#include <iostream>

class Rectangle {
public:
    explicit Rectangle(double l, double w) : length(l), width(w) {}
    virtual void print() const;

private:
    double length;
    double width;
};

void Rectangle::print() const { // print() method of base class
   std::cout << "Length = " << this->length << "; Width = " << this->width;
}

class Box : public Rectangle {
public:
    explicit Box(double l, double w, double h) : Rectangle(l, w), height(h) {}
    virtual void print() const; // virtual is optional here, but it is a good practice to remind it to the developer

private:
    double height;
};

void Box::print() const { // print() method of derived class
   Rectangle::print();  // Invoke parent print() method.
   std::cout << "; Height= " << this->height;
}

int main(int argc, char** argv) {
   Rectangle rectangle(5.0, 3.0);   rectangle.print();
   // outputs:
   // Length = 5.0; Width = 3.0

   Box box(6.0, 5.0, 4.0);
   // the pointer to the most overridden method in the vtable in on Box::print
   //box.print(); // but this call does not illustrate overriding

   static_cast<Rectangle&>(box).print(); // this one does   

   // outputs:
   // Length = 5.0; Width = 3.0; Height= 4 // INCORRECT  

   //But it actually outputs Length = 6; Width = 5; Height = 4

   getchar();
   return 0;

}

4 个答案:

答案 0 :(得分:3)

你是对的 - 提到的输出不正确。

演员表只是演示了一个框是一种矩形(从它继承),即使是一个矩形,方法覆盖仍然有效,Box方法的print版本将被召唤。

答案 1 :(得分:3)

随意修复维基百科中的评论:输出应该是Length = 6; Width = 5; Height = 4

另一部分是正确的:即使在Box.print()引用被静态转换为对其超类的引用之后调用Box的代码确实证明了如何覆盖虚方法适用于C ++。

证明同一点的另一种方法是使用指针而不是引用:

Rectangle *boxPtr = &box;
boxPtr->print();

答案 2 :(得分:2)

文章中的评论确实是错误的(现在已经修复);你应该打印6,5和4。

强制转换的目的是证明,即使你通过对基类(Rectangle)的引用来调用虚函数,它也会调用与对象的实际类型相关联的覆盖({ {1}}) - 您仍然可以获得Box打印的三个值,而不是Box::print()打印的两个值。

答案 3 :(得分:2)

这一行:static_cast<Rectangle&>(box).print();与此代码具有相同的效果:

Rectangle & r = box;
r.print();

也与此代码具有相同的效果:

Rectangle * r = &box;
r->print();

这意味着Box对象已创建(Box box(6.0, 5.0, 4.0); =在运行时,您看到Box)并且存储此对象的指针/引用的类型无关紧要。您将框存储为Rectangle*这一事实就是您在编译时看到的。

关于覆盖虚拟方法的最重要的事实是关于“将调用哪个方法?”在运行时决定。

希望这有帮助。