【问题标题】:How to make sure you have overriden (hide) a method in a derived class in C++?如何确保在 C++ 的派生类中覆盖(隐藏)了一个方法?
【发布时间】:2009-05-20 17:52:08
【问题描述】:
class Base {

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

};


class Derived : public Base {

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


 }

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

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

【问题讨论】:

  • “正确隐藏”是什么意思?函数要么被覆盖,要么被隐藏。不能两者兼而有之。
  • 您是否在问是否有某种方法可以获得与 c# override 关键字相同的行为?这个优秀的关键字确保该函数实际上覆盖了某些东西。由于函数签名的不同,当你打算不覆盖 C++ 中的某些内容时,这是一个简单的错误。
  • “隐藏”是指不公开吗?
  • 正确隐藏是指我实际上是在Derived中隐藏了Base的foo实现。在上面的实现中,我实际上并没有隐藏实现,因为我错过了成本。
  • 这就是所谓的“覆盖”。如果它不是虚拟的并且具有相同的名称,您无论如何都会隐藏它。如果它虚拟的并且你得到正确的签名,那么你覆盖它,这意味着你不隐藏它。

标签: c++ polymorphism


【解决方案1】:

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

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

编辑:根据您的编辑和其他 cmets,我认为您对隐藏在 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!你可能会收到一个编译器警告,告诉你双精度值将被截断。尽管采用双精度的函数签名显然是更好的匹配,但从未考虑过它 - 它已被隐藏。

【讨论】:

    【解决方案2】:

    “void foo() const”和“void foo()”就 C++ 而言是两个完全不同的函数。这就是为什么您看不到派生的“foo”将“foo”隐藏在 Base 中的原因。

    【讨论】:

    • 这不是真的,如果一个基类定义了一个函数,那么它会隐藏基类中所有同名的函数,即使它们有不同的参数(不相信我?试试看),让这些函数再次可见的方法是使用“using base::foo;”
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      如果您不想使其成为纯虚拟并因此强制实现,您可以只在Base 类中使foo() 的主体立即抛出异常。这样做的目的是强制任何实现者和用户实现覆盖,或者在他们尝试使用它时让它崩溃。

      我以前见过这种做法,虽然有点难看,但它确实有效。

      【讨论】:

        【解决方案5】:

        如果我正确理解了您的问题,您是在问如何确保 Derived 类强制覆盖该方法,而不使该方法纯在 Base 类中。

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

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

        【讨论】:

          【解决方案6】:

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

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

          但它存在三个问题:

          1. 它需要更改 Base 类,应禁止修改。
          2. 它可能比您需要的更强大,因为您可能希望允许从 Base 对象或显式调用 Base::foo()。
          3. 它使用 RTTI,意思是 vtbl,这可能就是您一开始不想使用虚函数的原因。

          【讨论】:

            猜你喜欢
            • 2015-08-18
            • 1970-01-01
            • 1970-01-01
            • 2018-08-18
            • 2011-06-01
            • 1970-01-01
            • 2011-05-14
            • 1970-01-01
            • 2014-04-14
            相关资源
            最近更新 更多