是否有人知道C ++中的语言特性或技术,以防止子类过度使用父类中的特定方法?
class Base {
public:
bool someGuaranteedResult() { return true; }
};
class Child : public Base {
public:
bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};
尽管它不是虚拟的,但仍然允许这样做(至少在我正在使用的Metrowerks编译器中),所有你得到的是关于隐藏非虚拟继承函数X的编译时警告。
答案 0 :(得分:33)
如果可以将final
说明符用于虚拟方法(随C ++ 11引入),则可以执行此操作。让我引用my favorite doc site:
在虚函数声明中使用时,final指定派生类不能覆盖该函数。
适应您的例子:
class Base {
public:
virtual bool someGuaranteedResult() final { return true; }
};
class Child : public Base {
public:
bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};
编译时:
$ g++ test.cc -std=c++11
test.cc:8:10: error: virtual function ‘virtual bool Child::someGuaranteedResult()’
test.cc:3:18: error: overriding final function ‘virtual bool Base::someGuaranteedResult()’
使用Microsoft编译器时,还要查看sealed
关键字。
答案 1 :(得分:12)
一些想法:
除此之外,我不知道一种语言功能会以某种方式锁定你的函数,以防止它被重载,并且仍然可以通过指向子类的指针/引用来调用。
祝你好运!答案 2 :(得分:6)
听起来你正在寻找的是等同于prevents a method from being overridden by a subclass的Java语言 final 关键字。
由于others这里有suggested,你实在无法阻止这种情况。此外,这似乎是frequently asked question。
答案 3 :(得分:2)
(a)我不认为使函数私有是解决方案,因为它只是从派生类隐藏基类函数。派生类总是可以定义具有相同签名的新函数。 (b)使函数非虚拟也不是一个完整的解决方案,因为如果派生类重新定义了相同的函数,那么总是可以通过编译时绑定来调用派生类函数,即obj.someFunction()其中obj是一个实例。衍生类。
我认为没有办法做到这一点。另外,我想知道您决定禁止派生类覆盖基类函数的原因。
答案 4 :(得分:2)
为澄清,大多数人误解了他的问题。他并没有问过“覆盖”一种方法,他在问是否有办法防止“隐藏”。简单的答案是“没有!”。
这是他的榜样
父类定义一个函数:
int foo() { return 1; }
继承Parent的子类定义了相同的函数AGAIN(不覆盖):
int foo() { return 2; }
您可以在所有编程语言上执行此操作。没有什么可以阻止编译此代码(编译器上的设置除外)。你得到的最好的结果是警告你隐藏了父方法。如果你调用子类并调用foo方法,你将得到2.你几乎破坏了代码。
这就是他的要求。
答案 5 :(得分:1)
关于隐藏非虚拟继承函数X的编译时警告。
更改编译器设置以使其成为错误而不是警告。
答案 6 :(得分:1)
我猜编译器警告你的是隐藏!!它实际上被覆盖了吗?
编译器可能会给出警告,但是在运行时,如果指针是父类的类型,则将调用父类方法,而不管它指向的对象的实际类型。
这很有趣。尝试为您的编译器制作一个小型独立测试程序。
答案 7 :(得分:1)
我正在寻找同样的东西,昨天来到这个[相当古老]的问题。
今天我发现了一个简洁的c ++ 11关键字:final
。我认为这可能对下一位读者有用。
答案 8 :(得分:0)
如果将子类作为其父类的一种类型,则非虚函数将调用父类的版本。
即:
Parent* obj = new Child();
答案 9 :(得分:0)
除非您将方法设为虚拟,否则子类无法覆盖它。如果您想让子类不要调用它,请将其设为私有。
所以默认情况下,C ++可以做你想要的。
答案 10 :(得分:0)
尝试阻止某人使用与子类中的函数相同的名称与尝试阻止某人使用与您在链接库中声明的相同的全局函数名称没有多大区别。
您只能希望那些意味着使用您的代码而不是其他代码的用户会小心他们如何引用您的代码,并且他们使用正确的指针类型或使用完全限定的范围。
答案 11 :(得分:0)
在您的示例中,不会覆盖任何函数。它隐藏了(它是一种退化的退化情况)。 错误发生在Child类代码中。正如csmba建议的那样,你所能做的就是改变你的编译器设置(如果可能的话);只要您不使用隐藏其自身功能的第三方库,它就应该没问题。
答案 12 :(得分:0)
从技术上讲,你可以防止虚拟功能被覆盖。但是你永远不可能改变或增加更多。这没有帮助。最好在faq lite建议的函数前面使用注释。
答案 13 :(得分:-1)
默认情况下,C ++方法是私有且不可覆盖的。
virtual
方法你可能是指超载吗?