从派生类中删除虚函数

Mat*_*ips 20 c++ inheritance derived-class c++11

我有一个虚拟基类函数,永远不应该在特定的派生类中使用.有没有办法'删除'它?我当然可以给它一个空的定义,但我宁愿让它尝试使用抛出编译时错误.C++ 11 delete说明符似乎是我想要的,但是

class B
{
    virtual void f();
};

class D : public B
{
    virtual void f() = delete; //Error
};
Run Code Online (Sandbox Code Playgroud)

不会编译; gcc,至少,明确地不允许我删除具有未删除的基本版本的函数.有没有其他方法来获得相同的功能?

The*_*dis 32

标准不允许这样做,但是您可以使用以下两种解决方法之一来获得类似的行为.

第一个是使用using改变方法私人的可见性,从而防止他人使用.该解决方案的问题是,在超类的指针上调用该方法不会导致编译错误.

class B
{
public:
    virtual void f();
};

class D : public B
{
private:
    using B::f;
};
Run Code Online (Sandbox Code Playgroud)

到目前为止,我发现在调用Ds方法时遇到编译时错误的最佳解决方案是使用static_assert带有继承自的泛型结构false_type.只要没有人调用该方法,结构就会保持不变,并且static_assert不会失败.

但是,如果调用该方法,则定义结构并且其值为false,因此static_assert失败.

如果没有调用该方法,但是您尝试在超类的指针上调用它,则D不会定义s方法,并且会出现undefined reference编译错误.

template <typename T>
struct fail : std::false_type 
{
};

class B
{
public:
    virtual void f() 
    {
    }
};

class D : public B
{
public:
    template<typename T = bool>
    void
    f()
    {
        static_assert (fail<T>::value, "Do not use!");
    }
};
Run Code Online (Sandbox Code Playgroud)

另一种解决方法是在使用该方法时抛出异常,但这只会在运行时抛出.

  • @Zingam如果放入`static_assert(false);`,它将永远不会编译。如果使用该方法,则仅初始化模板结构。 (2认同)

Ded*_*tor 10

该标准不允许您在派生类中删除任何基类成员,原因很简单:
这样做会破坏继承,特别是"is-a"关系.

由于相关原因,它不允许派生类定义在基类中删除的函数:
钩子不再是基类合同的一部分,因此它阻止您依赖先前不再保留的保证.

如果你想变得棘手,你可以强制一个错误,但它必须是链接时而不是编译时:
声明成员函数但不要定义它(这不是100%保证适用于虚拟功能虽然).
最好还看一下早期警告的GCC弃用属性__attribute__ ((deprecated)).
有关详细信息和类似的MS magic:C++标记为已弃用