C++中"virtual"关键字的放置位置

5
今天我在Visual Studio 2015中编写接口时,注意到了一些奇怪的行为。在函数标识符前放置"virtual"关键字通常不会产生影响,但是如果它放置在指针或引用后面,就会出现错误提示。请参考以下内容:
class B {};

class A
{
    virtual B fun1a(); // OK
    B virtual fun1b(); // OK

    virtual B& fun2a(); // OK
    B& virtual fun2b(); // ERROR, "expected an identifier"

    virtual B* fun3a(); // OK
    B* virtual fun3b(); // ERROR, "expected an identifier"

    virtual std::unique_ptr<B> fun4a(); // OK
    std::unique_ptr<B> virtual fun4b(); // OK
};

为什么会这样呢?

很明显,我可以通过始终将 virtual 关键字放在第一位来完全避免错误,但我希望能够以以下方式编写函数定义:

foo const & // return value and relevant keywords on one line
virtual bar( const baz &a ) const // function identifier, arguments, and relevant keywords on another line
{
    /* method implementation */
}

遗憾的是,对于返回引用或指针的函数来说,这是不可能的...

这个语法错误是特定于语言还是只存在于Visual Studio中?


7
在声明中,符号&*并不与类型相关,而是与你所声明的对象相关联。例如,B virtual &fun()是可以正常工作的。 - melpomene
2
[基于个人观点] 我强烈反对你想要编写的语法。它看起来非常陌生和令人困惑。 - Angew is no longer proud of SO
2个回答

2

你是否考虑使用尾置返回类型?它们可以让你实现将返回类型放在自己的一行的目标:

#include <memory>

class B {};

class A
{
    virtual auto fun1a()
    -> B;

    virtual auto fun1a() const
    -> B;

    virtual auto fun2a()
    -> B&;

    virtual auto fun2a() const
    -> B&;

    virtual auto fun2ac()
    -> B const&;

    virtual auto fun2ac() const
    -> B const&;

    virtual auto fun3b()
    -> B*;

    virtual auto fun3b() const
    -> B*;

    virtual auto fun3bc()
    -> B const*;

    virtual auto fun3bc() const
    -> B const*;

    virtual auto fun4a()
    -> std::unique_ptr<B>;

    virtual auto fun4a() const
    -> std::unique_ptr<B>;
};

需要注意的是,如果你使用 final 或者 override,那么它们必须放在返回类型之后:

virtual auto fun3bc() const
-> B const*
final;

需要记住的是,这种编码约定(将finaloverride放在自己的行上)非常不寻常。仅仅因为C++允许使用它,并不一定是一个好主意。


哦,那是个好主意。非常感谢! - Falkgaard
1
@Falkgaard:不用谢。但是我已经加了一个警告。 - Christian Hackl

1

试试这个

baz const // return value and relevant keywords on one line
virtual &foo::bar( arg a, arg b ) const // function identifier, arguments, and relevant keywords on another line
{
    /* method implementation */
}

谢谢,这确实有效。但是在方法标识符旁边而不是返回类型处放置*/&感觉有点奇怪。特别是如果返回值是指针的情况下。在这种情况下,我可以预见自己会错误地(假设我很累)只扫描第一行,并期望返回类型为const baz而不是指针。感觉有点反向,它不跟随类型... - Falkgaard
3
通常必填字段会靠近函数原型。 Virtual是一个可选的关键字。然而,返回类型(这里是baz&)是一个必填的关键字,总是必须提供。因此,通常人们将virtual放在最左边,将返回类型放在函数签名稍微靠近一些的位置。 - Ivan Salo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接