代码之家  ›  专栏  ›  技术社区  ›  Aaron Fischer

你能在C++中隐藏一个虚拟方法吗?

  •  4
  • Aaron Fischer  · 技术社区  · 15 年前

    我有一个带有虚拟函数的基类。

    virtual CString& Foo();
    

    我想在这样的子类中重载这个

    CString Foo();
    

    是否有隐藏基类虚拟函数的方法?类似于vb.net或c中的新关键字#

    6 回复  |  直到 13 年前
        1
  •  16
  •   Tomek Szpakowicz    15 年前

    为什么有人会这样做?它违反了基本类合同。 如果不想实现与基类具有相同接口的子类,那么为什么还要继承它呢? 使用合成。

    没有等价的c# 新的 关键字在C++中。 所以您不能取消方法的“虚拟性”。

    如果你 真正地 要做到这一点,您可以始终:

    • 将子类中的方法重写为private。

    • 创建重载。但是超载必须有不同的 参数 .

    但是如果你这样做了,我知道你的设计有问题。 我希望每个C++编译器至少把这两种情况都当作警告。

        2
  •  9
  •   David Rodríguez - dribeas    15 年前

    首先,坏消息是,不能用另一个仅在返回类型上不同的函数重写或隐藏虚拟函数。然后,另一个坏消息,C++给你足够的绳子,以悬挂你自己在许多你以前没有考虑过的方式,你可以得到类似的效果:

    struct base {
       virtual std::string const & f() { 
          static std::string s = "virtual"; 
          return s; 
       }
    };
    namespace detail {
       class place_holder; // no need to define it, it is just a place holder (duh)
    }
    struct derived : public base {
       std::string f( place_holder* p = 0 ) { return "crooked"; }
    };
    int main() {
       derived d; std::cout << d.f() << std::endl; // crooked
       base& b = d; std::cout << b.f() << std::endl; // virtual
    }
    

    诀窍在于,通过在派生类中定义具有相同名称和不同参数的方法,您实际上隐藏了基类(除非添加 using base::f 在派生类中,但调用将不明确)。同时,因为唯一添加的参数有一个默认值,所以您可以在没有参数的情况下调用它,编译器将为您添加默认参数。

    注意,实际上并不是从对象中移除方法,而是将其隐藏在派生类中。如果通过指向基类的指针或引用调用该方法,则虚拟方法仍然存在,并将被调用。

        3
  •  1
  •   Marcin Gil    15 年前

    首先,你不能重写

    virtual CString& Foo()
    

    具有

    CString Foo()
    

    因为它们的区别仅仅在于返回类型——这不会编译。

    如果函数带有签名

    int foo();
    

    virtual 在基类中-派生类中具有相同签名的函数也将是虚拟的;您不必指定 事实上的 在派生类中。

    有关虚拟函数的详细信息(以及更多!)你可以偷看 C++ FAQ Lite .

        4
  •  1
  •   Akshay    14 年前
    1. 您的代码将无法编译。我想你知道,这就是你问这个问题的原因。
    2. 但是,您需要关注的只是隐藏基类虚拟函数。为此,请创建另一个具有基类函数以外的其他参数的函数。这将隐藏基类函数。
        5
  •  1
  •   Karl von Moor    13 年前

    从技术上讲,可以通过在派生类static中声明方法:

    static CString& Derived::foo()
    

    这听起来很奇怪,但是尝试一下-编译器会吃东西并发出警告。 覆盖将被忽略,并且 virtual Base::foo() 将被隐藏并替换为静态 Derived::foo() .

    不过,你为什么需要那样的东西?

        6
  •  0
  •   Pavel Minaev    15 年前

    不,不是真的。即使您引入一个中间类来创建继承的方法 private 这是无济于事的,因为私有的虚拟方法在C++中仍然是可重写的。