2012-06-29 93 views
11

我想在C++中理解这一点。 如果类A有一个非虚方法,并且扩展A的类B覆盖该方法,我可以创建B的一个实例并以某种方式使用B中定义的方法? 有没有必要重写一个非虚方法?我可以使用覆盖非虚方法的方法吗?

+1

你所描述的称为*隐藏*,而不是覆盖。看看这里,例如:http://stackoverflow.com/questions/2161462/c-inheritance-and-function-overriding – jrok

回答

31

是否有必要重写一个非虚方法?

你实际上并没有覆盖,但是这是行为,即

B* b = new B(); 
A* a = new B(); 
b->method(); //Calls B's method 
a->method(); // Calls A's method 

因此,指针/引用类型决定调用的方法。

我可以创建一个B的实例,并以某种方式使用B中定义的方法吗?

是的。指针/引用类型必须是B类型的(参见前面的例子)。

如果不申报methodvirtual,你不能覆盖它,但你可以隐藏它。

+0

很好的答案,谢谢 – Eyal

+1

一个“gotcha”是当'A'反过来是从一些基类(或实现一个接口)派生'virtual method()',在这种情况下'a->方法()'实际上会调用'B.method()'... – BadCash

+0

@Chip你错过了强调差异。这个答案只有BadCashs评论完成。 – ManuelSchneid3r

9

如果从AB继承,并重新定义了A定义的方法,那么B新实例将调用B的版本。但是,如果该方法不是虚拟的,则不存在多态行为,因此如果B的实例被引用为A,则该方法将为A。例如:

struct A { 
    void foo() { std::cout << "A::foo" << std::endl; } 
}; 

struct B : public A { 
    void foo() { std::cout << "B::foo" << std::endl; } 
}; 

B b; 
b.foo(); 
A *a = &b; 
a->foo(); 

的代码的输出以上将是:

B::foo 
A::foo 

然而,如果foo方法已经虚拟的,然后将B::foo已打印的两倍。

+0

写得很好! :) – niknak

2

如果函数不是virtual那么变量的类型决定了执行被分派太:

#include <iostream> 

using namespace std; 

struct A { 
    void f() { cout << "A" << endl; } 
}; 

struct B : public A { 
    void f() { cout << "B" << endl; } 
}; 

int main(int args, char** argv) { 

    B b; 
    A& a = b; 

    b.f(); 
    a.f(); 

    return 0; 
} 
0
  • 没有,没有机制来覆盖类A.
  • 非虚拟方法
  • 是的,则可以通过使用范围解析运营商A使用从A类B中过载的非虚拟方法::方法名