有没有办法防止方法在子类中被覆盖?

时间:2020-03-05 18:41:00  来源:igfitidea点击:

有人知道C ++中的语言功能或者技术可以防止子类过度使用父类中的特定方法吗?

class Base {
public:
    bool someGuaranteedResult() { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

即使它不是虚拟的,也仍然允许(至少在我正在使用的Metrowerks编译器中),我们得到的只是关于隐藏非虚拟继承函数X的编译时警告。

解决方案

回答

如果将子类作为其父类的类型来寻址,则非虚拟函数将调用父类的版本。

IE:

Parent* obj = new Child();

回答

一些想法:

  • 将功能设为私有。
  • 不要将功能虚拟化。但这实际上并不能阻止函数被另一个定义遮盖。

除此之外,我不知道一种语言功能会以某种方式锁定函数,从而防止该函数被重载并仍然能够通过指向子类的指针/引用来调用它。

祝你好运!

回答

C ++方法是私有的,默认情况下不可覆盖。

  • 我们不能覆盖私有方法
  • 我们不能覆盖非virtual方法

我们也许是在指超载?

回答

a compile time warning about hiding non-virtual inherited function X.

更改编译器设置,使其变为错误而不是警告。

回答

除非我们将方法设为虚拟方法,否则子类无法覆盖它。如果要阻止子类调用它,请将其设为私有。

因此,默认情况下,C ++可以满足需求。

回答

听起来我们正在寻找的是与Java语言的final关键字等效的关键字,该关键字防止方法被子类覆盖。

正如这里的其他人所建议的那样,我们确实无法避免这种情况。同样,这似乎是一个经常问到的问题。

回答

尝试阻止某人使用与子类中的函数相同的名称与尝试阻止某人使用与我们在链接库中声明的相同的全局函数名称没有太大不同。

我们只能希望那些打算使用代码而不是其他人的用户会小心他们如何引用代码,以及他们使用正确的指针类型或者使用完全限定的范围。

回答

(a)我不认为将函数设为私有是解决方案,因为这只会对派生类隐藏基类函数,派生类始终可以定义具有相同签名的新函数。
(b)使函数成为非虚拟函数也不是一个完整的解决方案,因为如果派生类重新定义了相同的函数,则始终可以通过编译时绑定即obj.someFunction()来调用派生类函数,其中obj是派生类。

我不认为有这样做的方法。此外,我想知道我们决定禁止派生类覆盖基类函数的原因。

回答

在示例中,没有函数被覆盖。相反,它是隐藏的(这是过载的一种退化情况)。
错误在Child类代码中。正如csmba所建议的,我们所能做的就是更改编译器设置(如果可能);只要我们不使用隐藏其自身功能的第三方库就可以了。

回答

我猜编译器警告是隐藏的!它实际上被覆盖了吗?

编译器可能会警告我们,但是在运行时,如果指针的类型为父类,则将调用父类方法,而不管其指向的对象的实际类型如何。

这是有趣的。尝试为编译器制作一个小的独立测试程序。

回答

为了澄清起见,你们中的大多数人都误解了他的问题。他不是在问"重写"方法,而是在问是否有防止"隐藏"的方法。简单的答案是"没有!"。

这又是他的榜样

父类定义一个函数:

int foo() { return 1; }

继承父级的子级类定义了相同的函数AGAIN(不可覆盖):

int foo() { return 2; }

我们可以在所有编程语言上执行此操作。没有什么可以阻止此代码编译的(编译器上的设置除外)。我们得到的最好的结果是警告我们正在隐藏父级的方法。如果调用子类并调用foo方法,将得到2. 实际上已经破坏了代码。

这就是他的要求。

回答

从技术上讲,我们可以防止虚拟函数被覆盖。但是我们将永远无法更改或者添加更多内容。那无济于事。如常见问题建议的那样,最好在函数前使用注释。