使用下面给出的结构定义…
struct A {
virtual void hello() = 0;
};
方法# 1:
struct B : public A {
virtual void hello() { ... }
};
方法# 2:
struct B : public A {
void hello() { ... }
};
这两种重写hello函数的方法有什么区别吗?
使用下面给出的结构定义…
struct A {
virtual void hello() = 0;
};
方法# 1:
struct B : public A {
virtual void hello() { ... }
};
方法# 2:
struct B : public A {
void hello() { ... }
};
这两种重写hello函数的方法有什么区别吗?
当前回答
我肯定会为子类包含Virtual关键字,因为
我,可读性。 2这个子类可以向下派生,你不希望派生类的构造函数调用这个虚函数。
其他回答
不需要,派生类的虚函数重写上的virtual关键字不是必需的。但是值得一提的是一个相关的缺陷:无法覆盖虚函数。
如果您打算重写派生类中的虚函数,但在签名中犯了错误,从而声明了一个新的不同的虚函数,则会发生重写失败。此函数可能是基类函数的重载,也可能在名称上不同。无论是否在派生类函数声明中使用virtual关键字,编译器都无法判断您打算重写基类中的函数。
然而,谢天谢地,c++ 11显式重写语言特性解决了这个缺陷,它允许源代码清楚地指定一个成员函数用于重写基类函数:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(int) override; // ill-formed - doesn't override a base class method
};
编译器将发出编译时错误,编程错误将立即显现(也许Derived中的函数应该将float作为参数)。
参考WP: c++ 11。
在派生类中不需要virtual关键字。下面是c++标准草案(N3337)的支持文档(强调我):
10.3虚函数 如果虚成员函数vf在类Base和类Derived(直接或间接从Base派生)中声明,则声明了一个与Base::vf同名、形参类型-list(8.3.5)、cv- qualifier和ref-qualifier(或没有相同)的成员函数vf,则Derived::vf也是虚函数(无论是否这样声明),并且它覆盖Base::vf。
我肯定会为子类包含Virtual关键字,因为
我,可读性。 2这个子类可以向下派生,你不希望派生类的构造函数调用这个虚函数。
virtual关键字应该添加到基类的函数中,以使它们可重写。在您的示例中,结构体A是基类。虚指的是在派生类中使用这些函数。然而,如果你想要你的派生类本身也是基类,你想要那个函数是可重写的,那么你就必须把虚函数放在那里。
struct B : public A {
virtual void hello() { ... }
};
struct C : public B {
void hello() { ... }
};
这里C继承自B,所以B不是基类(它也是一个派生类),C是派生类。 继承图如下所示:
A
^
|
B
^
|
C
所以你应该把虚函数放在可能有子基类的函数前面。Virtual允许你的孩子覆盖你的函数。将虚函数放在派生类中的函数前面并没有错,但这不是必需的。尽管如此,还是建议这样做,因为如果有人想从你的派生类继承,他们会不高兴方法重写没有像预期的那样工作。
因此,在所有涉及继承的类中,将virtual放在函数前面,除非您确定该类不会有任何需要重写基类函数的子类。这是很好的练习。
添加“virtual”关键字是很好的做法,因为它可以提高可读性,但不是必须的。在基类中声明为虚的函数,并且在派生类中具有相同的签名,默认情况下被视为“虚”函数。