【问题标题】:Can i use a method overriding a non-virtual method?我可以使用覆盖非虚拟方法的方法吗?
【发布时间】:2012-06-29 22:00:20
【问题描述】:

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

【问题讨论】:

标签: c++ polymorphism overriding


【解决方案1】:

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

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

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

所以,指针/引用类型决定了调用的方法。

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

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

如果您不将method 声明为virtual,则不能覆盖它,但可以隐藏它。

【讨论】:

  • 一个“陷阱”是A 又派生自某个声明virtual method() 的基类(或实现接口)的情况,在这种情况下a->method() 实际上会调用@ 987654327@...
  • @Chip 你错过了强调差异。此答案仅包含 BadCashs 评论。
  • @ManuelSchneid3r 虽然你是对的,但在 BadCash 的情况下,A 的方法是虚拟的。问题是关于非虚拟方法的。在 C++ 中,“一次虚拟,永远虚拟”。
【解决方案2】:

如果B 继承自A,并重新定义了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 将被打印两次。

【讨论】:

  • 写得好! :)
【解决方案3】:

如果函数不是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;
}

【讨论】:

    【解决方案4】:
    • 不,没有机制可以覆盖 A 类中的非虚拟方法。
    • 是的,您可以通过使用范围解析运算符 A::methodName 来使用在 B 中重载的类 A 中的非虚拟方法

    【讨论】:

      猜你喜欢
      • 2012-06-19
      • 2018-01-28
      • 1970-01-01
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多