简体   繁体   English

派生类中非虚拟函数的C ++同名与`final`说明符冲突

[英]C++ same name for non-virtual function in derived class conflicts with `final` specifier

This has the feeling of a complete newbie question, but why does the following code not compile when the final specifier is used for B::operator() ? 这有一个完整的新手问题的感觉,但是当将final说明符用于B::operator()时,为什么以下代码没有编译?

struct A
{
    virtual void operator()() const = 0;
};

// the CRTP-component is not really necessary here
// but it possibly makes more sense in that it could be applied like this in reality
//
template<typename Derived>
struct B : A
{
    virtual void operator()() const override final
    {
        static_cast<Derived const&>(*this).operator()();
    }
};

struct C : B<C>
{
    void operator()() const
    {
        //do something
    }
};

int main()
{
    C()();
}

G++ prints the following error message : G ++打印以下错误消息

main.cpp:17:14: error: virtual function 'virtual void C::operator()() const'
         void operator()() const
              ^
main.cpp:9:22: error: overriding final function 'void B<Derived>::operator()() const [with Derived = C]'
         virtual void operator()() const override final
                      ^

I would have thought it works as the non-virtual C::operator() does not override the virtual functions in its base classes? 我会以为它可以工作,因为非虚拟C::operator()不会在其基类中覆盖虚拟函数? How can I bring this to work (--without changing the name of C::operator() )? 我如何才能使用它(在不更改C::operator()名称的情况下)?


EDIT : As pointed out by several users, the answer is simply that the virtual -keyword in the derived class is redundant (whereas I thought leaving it out would prevent from inheriting). 编辑 :正如几个用户所指出的,答案很简单,派生类中的virtual -keyword是多余的(而我认为将其保留会阻止继承)。 However, the goal I had in asking this -- namely a consistent interface throughout the dynamic and static inheritance hierarchy -- can be solved by using a non-virtual operator[] throughout and couple classes A and B by a virtual function apply : 但是,我提出这个目标的目的是在整个动态和静态继承层次结构中实现一致的接口,可以通过在整个过程中使用非虚拟operator[]来解决,并通过一个虚拟函数apply耦合类AB

struct A
{
    void operator()() const
    {
        this->apply();
    }

protected:
    virtual void apply() const = 0;
};

template<typename Derived>
struct B : A
{
    void operator()() const
    {
        static_cast<Derived const&>(*this).operator()();
    }

protected:
    virtual void apply() const override final
    {
        this->operator()();
    }
};

struct C : B<C>
{
    void operator()() const
    {
        //do something
    }
};

int main()
{
    C()();
}

If a function is declared virtual in a base class, then a function declared with the same name and parameter list is implicitly virtual in derived classes, whether or not you use the virtual keyword. 如果在基类中将函数声明为virtual函数,则无论您是否使用virtual关键字,在派生类中声明具有相同名称和参数列表的函数都是隐式virtual函数。 You cannot make C::operator()() non-virtual. 您不能使C::operator()()是非虚拟的。

A function in a derived class with the same signature as a virtual function in a base class overrides that virtual function from the base class. 派生类中的功能与基类中的虚函数具有相同签名的函数会覆盖基类中的虚函数。 That makes it a virtual function, even if/though the declaration in the derived class doesn't use the virtual key word. 即使/尽管派生类中的声明不使用virtual关键字,这也使其成为虚拟函数。

That can't be changed, so if you really need to have a function with the same name in a derived class that doesn't override the virtual function from the base class (and in the process, become virtual itself and in this case, violate the final in B ) you'll need to change the signature of the function in the derived class. 这是无法更改的,因此,如果您确实需要在派生类中拥有一个具有相同名称的函数,并且该函数不覆盖基类中的虚函数(并且在此过程中,请成为虚函数本身,在这种情况下,违反Bfinal ),您需要在派生类中更改函数的签名。 That can mean a different name, different parameter list, or different qualifiers. 这可能意味着不同的名称,不同的参数列表或不同的限定词。 I'd treat the latter two with extreme caution though--the compiler will be able to sort out the mess you've made, but many human readers may (very easily) be surprised. 不过,我会非常谨慎地对待后两者-编译器将能够整理出您造成的混乱,但是许多人类读者可能(非常容易)感到惊讶。

If I were reviewing such code, I'd probably cite this as a problem, and the author would need to provide very solid reasoning for why it was truly necessary to get it approved. 如果我正在审查这样的代码,可能会把它当作一个问题,并且作者将需要提供非常扎实的理由,说明为何确实有必要使它获得批准。

As an override (because it has the same signature as the virtual function in a base class), the override conflicts with the final specified in its base class. 作为覆盖(因为它与基类中的虚函数具有相同的签名),所以覆盖与基类中指定的final冲突。

One fix (or rather workaround) is to give that function a defaulted argument, so that it has a different type and hence not an override, and a better approach is to fix the design. 一种解决方法(或更确切地说,解决方法)是为该函数提供默认参数,以使其具有不同的类型,因此不能覆盖,更好的方法是修复设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++继承从基类指针访问派生类中的非虚函数 - C++ Inheritance accessing a non-virtual function in derived class from base class pointer 在派生类中声明为非虚函数的虚函数 - virtual function declared non-virtual in a derived class 在C ++中重新定义非虚函数 - redefine a non-virtual function in C++ 在基类'Destructor中调用派生类'(非虚)function - Call a derived class' (non-virtual) function in the base class' Destructor C ++最终非虚拟类是否可以重新解释为可安全使用的数组? - Is c++ final non-virtual class reinterpreted as array safe for use? 在C ++中,是否允许将其强制转换为仅添加非虚拟方法的派生类? - In C++, is it allowed to cast to a derived class that only adds non-virtual methods? 虚函数是否覆盖基类中同名的非虚函数? - Does a virtual function override a non-virtual function of the same name in a base class? C++:继承重载的非虚方法和虚方法都具有相同的名称会导致问题 - C++: inheriting overloaded non-virtual method and virtual method both with the same name causes problem 如果将虚函数或非虚函数添加到C ++中的基类中,是否必须重新编译整个类层次结构? - Must the entire class hierarchy be recompiled if a virtual or non-virtual function is added to the base class in C++? C ++:在非虚函数中使用纯虚函数 - C++: use a pure virtual function in a non-virtual function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM