有谁知道 C++ 中的语言功能或技术可以防止子类覆盖父类中的特定方法?

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

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

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

有帮助吗?

解决方案

几个想法:

  1. 将您的函数设为私有。
  2. 不要让你的函数成为虚拟的。但这实际上并不能阻止该函数被另一个定义所掩盖。

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

祝你好运!

其他提示

当您可以使用 final 虚拟方法的说明符(C++11 中引入),你可以做到。让我引用一下 我最喜欢的文档网站:

当在虚函数声明中使用时,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 关键词。

听起来你正在寻找的是 Java 语言的等价物 最终的 关键字那个 防止方法被子类覆盖.

作为 其他的 这里有 建议, ,你确实无法阻止这一点。另外,这似乎是一个相当 常见问题.

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

我认为没有办法做到这一点。另外,我想知道您决定禁止派生类覆盖基类函数的原因。

澄清一下,你们大多数人都误解了他的问题。他不是在问“重写”方法,而是在问是否有办法防止“隐藏”。简单的答案是“没有!”。

这是他的例子

父类定义了一个函数:

int foo() { return 1; }

继承父类的子类再次定义相同的函数(不重写):

int foo() { return 2; }

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

这就是他要问的。

关于隐藏非虚继承函数 X 的编译时警告。

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

我猜编译器警告你的内容正在隐藏!它实际上被覆盖了吗?

编译器可能会向您发出警告,但在运行时,如果指针属于父类类型,则将调用父类方法,无论它指向的对象的实际类型是什么。

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

我正在寻找相同的内容,昨天遇到了这个[相当老的]问题。

今天我发现了一个简洁的 c++11 关键字: final 。我认为这可能对下一位读者有用。

http://en.cppreference.com/w/cpp/language/final

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

IE:

Parent* obj = new Child();

除非将该方法设为虚拟方法,否则子类无法重写它。如果您想阻止子类调用它,请将其设为私有。

所以默认情况下 C++ 会做你想做的事。

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

您只能希望那些想要使用您的代码(而不是其他人的代码)的用户会小心他们引用您的代码的方式,并使用正确的指针类型或使用完全限定的范围。

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

从技术上讲,您可以防止虚拟函数被覆盖。但您将永远无法更改或添加更多内容。那是无济于事的。最好按照 faq lite 的建议在函数前面使用注释。

默认情况下,C++ 方法是私有的且不可重写。

  • 您不能覆盖私有方法
  • 您不能覆盖非virtual 方法

您可能指的是超载吗?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top