我是C ++的初学者,这些天我正在研究虚拟功能。 有些问题让我很困惑。
例如:
class A {
public:
virtual void f() {
//do something;
}
}
class B: public A {
public:
virtual void f() {
//do something;
}
}
class A
包含虚拟函数f()
,class B
继承它。在class B
内,函数f()
也被声明为虚拟,这是否意味着f()
中的class B
重载f()
中的class A
?是否允许继承B
的类重载f()
?或者B
是否定义了与f()
中的class A
不同的新虚拟函数?
虚函数提供了一种重载方法的方法。如果B
继承A
并且未将f()
声明为virtual
,则继承C
的类B
可以重载f()
并实现多态?
答案 0 :(得分:4)
在类B内部,函数f()也被声明为虚拟,所以这意味着类A中的f()在类A中重载f()
不,它没有重载。它覆盖。关键字virtual
在类B
中也是可选的。无论您是否撰写B::f()
,virtual
始终都是virtual
函数。
当您使用相同名称但不同参数定义函数时,将使用术语 overload 。在您的情况下,函数f
的签名在两个类中完全相同,这意味着它不是重载;派生类基本上覆盖 f()
的基类定义。
答案 1 :(得分:2)
虚拟关键字允许您 覆盖 功能而不是 重载 。
此外,虚拟属性是继承的,因此虚拟关键字对于f()
中的class B
是可选的。
答案 2 :(得分:1)
当你声明一个虚函数时,你真正对编译器说的是你希望这个函数以多态方式运行。也就是说,如果我们有以下内容,请从您的示例中获取:
A* foo = new B();
foo->f();
它将调用B的“f”函数而不是A的“f”函数。更进一步,如果我们有一个继承自B的C,就像你说的那样:
class C : public B{}
B* foo = new C();
foo->f():
这称为B的“f”。如果你在C中定义了它,它就会调用C的方法。
要解释虚拟和非虚拟之间的不同行为,请使用此示例:
struct Foo{
virtual void f();
void g();
};
struct Bar{
virtual void f();
void g();
};
Foo* var = new Bar();
var->f(); //calls Bar's f
var->g(); //calls Foo's g, it's not virtual
有意义吗?
答案 3 :(得分:0)
由于A :: f是虚拟的,而B :: f具有相同的签名,因此可以说B :: f 会覆盖 A :: f。 / p>
这意味着:
A * p = new B;
p->f(); // invokes B::f
编辑:以下是完全错误的(见评论):
由于B :: f也是虚拟的,因此B的子类可能会再次覆盖它。如果B:f不是虚拟的,那么在子类中具有相同签名的任何方法都只会遮蔽它(也就是说,它将是一种不同的方法)。
因此,行为取决于父母。