防止覆盖和/或隐藏基类功能(C++ 11)

use*_*886 9 c++ inheritance c++11

自从我学习C++以来,我甚至想要防止隐藏基类非虚函数一段时间,我不确定这是否符合道德规范,但C++ 11的功能给了我一个想法.假设我有以下内容:

bases.h ....

#ifndef baseexample_h
#define baseexample_h

#include <iostream>

class Base{
    public:  
    void foo() {
        std::cout << "Base.foo()\n" << std::endl;
    }
};

class Derived: public Base{ 
    public:
    void foo(){
        std::cout << "Derived.foo()\n" << std::endl;
    }   
};

#endif
Run Code Online (Sandbox Code Playgroud)

和main.cpp ...

#include "bases.h"
#include <iostream>

int main()
{

    Base base;
    Derived derived; 

    base.foo();
    derived.foo();

    std::cin.get();

    return 0;
};
Run Code Online (Sandbox Code Playgroud)

当然是输出

Base.foo()

Derived.foo()
Run Code Online (Sandbox Code Playgroud)

因为派生的foo()函数隐藏了基本的foo函数.我想防止可能的隐藏,所以我的想法是将头文件基本定义更改为:

//.....
class Base{
    public:  
    virtual void foo() final {
        std::cout << "Base.foo()\n" << std::endl;
    }
};

class Derived: public Base{ 
    public:
    void foo(){ //compile error
        std::cout << "Derived.foo()\n" << std::endl;
    }   
};
//......
Run Code Online (Sandbox Code Playgroud)

这似乎强制执行我想要的编译错误,防止在c ++中覆盖AND/OR隐藏,但我的问题是,这是一个很好的做法,因为foo()从来不是一个虚拟函数开始?因为我有点滥用虚拟关键字,所以这有不足之处吗?谢谢.

Lig*_*ica 5

我会说,是的,这是不好的做法。您在不需要时引入了多态,只是为了防止名称隐藏。

但是,隐藏姓名有什么不好呢?显然,无论出于何种原因,设计都Derived希望将功能隐藏foo在其基类中。这就是它的作用-也许它自己进行调用,Base::foo然后执行中所需的一些其他活动Derived

试图颠覆这已经够糟糕了;通过选择不想要的语言功能来做到这一点甚至更糟。

如果确实需要调用基本函数,请使用derived.Base::foo(),但请注意,您实际上在破坏该类的API Derived,而应改为按文档所述使用。

  • “显然,无论出于何种原因,Derived的设计都希望将函数foo隐藏在其基类中”。可能是一个偶然的相似名称选择,或者可能是在编写“派生”之后将“ foo”添加到“基础”中,然后直到测试/质量检查之前,编译器/ IDE理想地捕获的一个简单错误才被发现。我不相信C ++可以解决这个问题,但这很遗憾。 (11认同)