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