如何确保在C ++中的派生类中覆盖(隐藏)方法?

时间:2009-05-20 17:52:09

标签: c++ polymorphism

class Base {

    public:
         void foo() const {
             std::cout << "foo const" << std::endl;
         }

};


class Derived : public Base {

  public:
         void foo()  {
             std::cout << "foo"<< std::endl;
         }


 }

我想确保为Base正确隐藏了foo()const。是的,这是一个坏主意,也许我应该让Base :: foo()const成为一个纯虚拟的,要求Dervied :: foo()正确覆盖 - 但是让我说我​​不能让Base :: foo()const纯虚拟。有没有更好的方法来确保Base :: foo()const在Derived中正确隐藏?

编辑:我想确保在Derived中我已正确隐藏了基本实现。

6 个答案:

答案 0 :(得分:4)

只需在派生类中定义成员函数foo,就可以隐藏基类中的所有foo函数。

你需要稍微改进一下这个问题 - 你是否担心派生类中的foo不能替代基类中的foo?我很难确定你真正要求的是什么。

编辑:根据您的编辑和其他评论,我认为您对隐藏在C ++中的工作方式存在误解。在这种情况下,一个函数是const而另一个函数不是无关紧要 - 一旦C ++在派生类中找到函数foo,它就会停止在其他任何地方查找!这对人们来说通常是一个巨大的陷阱。请考虑以下事项:

class Base
{
    void foo(double d)
    {
        cout << d;
    }
};
class Derived : public Base
{
    void foo(int i)
    {
        cout << i;
    }
};

Derived obj;
obj.foo(123.456);

您认为输出是什么?这是123!你可能有一个编译器警告告诉你双值将被截断。即使采用double的函数签名显然是更好的匹配,但它从未被考虑过 - 它已被隐藏。

答案 1 :(得分:1)

你确定要从Base隐藏foo()吗?如果要利用多态性,则需要将foo()的基本版本设为虚拟。但它不一定是纯粹的。否则你会得到静态绑定 - 你想要吗?

答案 2 :(得分:1)

“void foo()const”和“void foo()”就C ++而言是两个完全不同的函数。这就是为什么你没有看到Derived的“foo”隐藏了基地的“foo”。

答案 3 :(得分:0)

如果我已正确理解您的问题,那么您就会问如何确保Derived类强制覆盖该方法,而不会在Base类中使该方法变为纯粹。

通过确保所有派生类提供方法的实现,恕我直言,你暗示Base类中的方法实际上并没有用于任何目的。对象必须调用方法Derived的任何foo()类版本。因此,在我看来,该方法应该是纯粹的虚拟。我相信,我认为没有其他方法可以实现这一点。

另请注意,在您的示例中,您更改了foo()BaseDerived的签名。这使Base类方法在Derived类中不可见。除非您使用using Base::foo,否则foo()类将无法看到方法Derived

答案 4 :(得分:0)

在Base :: foo()中,您可以执行以下操作:

assert (dynamic_cast<const Derived*> (this) == NULL);

但它有三个问题:

  1. 它需要更改Base类,应该关闭以进行修改。
  2. 它可能比您需要的更强大,因为您可能希望允许从Base对象或显式调用Base :: foo()。
  3. 它使用RTTI,这意味着一个vtbl,这可能就是你不想开始使用虚拟功能的原因。

答案 5 :(得分:0)

如果你不想让它成为纯虚拟的,从而强制执行,你可能只是让foo()类中Base的主体立即抛出异常。这样做的目的是强制任何实现者和用户实现覆盖,或者在尝试使用它时将其炸毁。

我之前已经看过这件事了,虽然它有点难看,但它确实有效。