我有一个带虚函数的基类。
virtual CString& Foo();
我想在子类中重载此类
CString Foo();
有没有办法隐藏基类的虚函数?类似于vb.net中的new关键字或C#
答案 0 :(得分:16)
为什么有人会这样做?它打破了基类合同。 如果您不想实现与基类具有相同接口的子类,为什么要继承? 使用组合。
C ++中没有等效的C# new 关键字。 所以你不能取消方法的'虚拟'。
如果真的想要这样做,你可以随时:
将子类中的方法重写为private。
创建过载。但是重载必须具有不同的参数。
但如果你这样做,恕我直言你的设计有问题。 我希望每个C ++编译器都至少捕获这两种情况作为警告。
答案 1 :(得分:9)
首先,坏消息是你不能用另一个仅在返回类型上有所不同的函数覆盖或隐藏虚函数。然后是另一个坏消息,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
,但随后调用将是暧昧)。同时,由于唯一添加的参数有一个默认值,你可以不带参数调用它,编译器会为你添加默认参数。
请注意,您实际上并未从对象中删除该方法,而是将其隐藏在派生类中。如果通过指针或对基类的引用调用该方法,则虚方法仍然存在并将被调用。
答案 2 :(得分:1)
首先你无法覆盖
virtual CString& Foo()
与
CString Foo()
因为它们之间的区别仅仅是返回类型 - 这不会编译。
如果是带签名的功能
int foo();
在基类中是virtual
- 派生类中具有相同签名的函数也将是虚拟的;您不必在派生类中指定virtual
。
有关虚拟功能的更多信息(以及更多!),您可以查看C++ FAQ Lite。
答案 3 :(得分:1)
答案 4 :(得分:1)
从技术上讲,你可以通过在派生类static中声明方法:
static CString& Derived::foo()
这听起来很奇怪,但尝试一下 - 编译器会吃掉并产生警告。
覆盖将被忽略,virtual Base::foo()
将被隐藏并替换为静态Derived::foo()
。
为什么你需要这样的东西呢?
答案 5 :(得分:0)
不,不是真的。即使你引入了一个中间类来创建继承的方法private
,它也无济于事,因为私有虚方法在C ++中仍然可以覆盖。