派生时方法应该始终是虚拟的吗?

时间:2014-05-06 20:38:29

标签: c++

标题说明了一切(我不确定何时使用virtual关键字)。在这种情况下,函数SaySomething()应该是virtual吗? (或者在使用指针时它可能只是virtual?)

#include <iostream>

class A{
    public:
        void SaySomething(){
            std::cout << "aaaaaa";
        }
};

class B : public A{
    public:
        void SaySomething(){
            std::cout << "bbbbbbb";
        }
};

int main(){
    A objectA;
    B objectB;

    objectA.SaySomething();
    std::cout << std::endl;
    objectB.SaySomething();

    return 0;
}

3 个答案:

答案 0 :(得分:3)

从技术上讲,在这种情况下,函数B::SaySomething不需要virtual:编译器知道每个对象的运行时类型,因此在两种情况下都会调用正确的方法。

但是,它与基类同名A::SaySomething覆盖它的事实可能会误导代码的读者。如果您打算隐藏,而不是覆盖类A::SaySomething中的B,那么最佳做法是为成员函数指定一个不同的名称。

以下是重要的情况:

B b;
A &ab(b);
b.SaySomething();  // Calls B::SaySomething
ab.SaySomething(); // Calls A::SaySomething

更改引用同一对象的方式时的行为会改变方法的行为,而不是代码的读者所期望的行为。如果你使A::SaySomething为虚拟,则两个调用都会产生相同的行为。

答案 1 :(得分:0)

如果你有:

class A {
    virtual void f() { cout << 1 << endl; }
};

class B : public A {
    virtual void f() { cout << 2 << endl; }
};

然后当你在这样的代码中使用它时:

A* a = new B();
a->f();

您的程序将编写2,因为您使用了virtual。它动态地解析指向的对象是B类型,尽管指针是A类型。

如果你不使用virtual,它将打印1并使用指针类型类中的函数。

答案 2 :(得分:0)

virtual关键字是在C ++中启用polymorphism的关键字。您的示例严格来说是非多态的,因为方法调用解析是静态的。所以在你的例子中没有必要。

但是,如果你有......

class Shape {

  virtual double area() = 0;
}

class Circle : public Shape {

  virtual double area() {
    return PI * r * r;
  }
}

class Square : public Shape {

  virtual double area() {
    return h * w;
  }
}

代码......

Shape* shapes[2];

shapes[0] = new Circle(1);
shapes[1] = new Square(1, 1);

for (int i=0; i<2; i++)
    cout << "shape[" << i << "] area -> " << shapes[i]->area();

会打印圆圈和方块的区域......

shape[0] area -> 3.1415926..
shape[1] area -> 1