C ++:隐藏规则的基本原理
C ++ 隐藏规则的基本原理是什么?
class A { void f(int); } class B : public A { void f(double); } // B::f(int) is hidden
-
如果这是一个有意义的function,我认为也应该可以隐藏函数而不用定义具有相同名称的新函数:像这样的东西:
class B : public A { hide void f(double); }
但这是不可能的。
-
我不认为这简化了编译器的工作,因为编译器无论如何都必须能够在显式使用
using
指令时取消隐藏函数:class B : public A { using A::f; void f(double); } // B::f(int) NOT hidden
那么,怎么会有一个隐藏的规则?
嗯,这三个答案看起来都不错,而且对隐藏规则也显示出不同的理由。 我不确定我应该接受哪个答案。
这是一个棘手的问题,但显然这个想法是,这个隐藏function有助于避免在修改基类(否则可能“窃取”之前由派生类处理的调用)时出现细微的错误。 仍然在基类的变化可以影响编译派生类的结果,所以我不认为我理解100%这个解释。
我同意这个话题经常被讨论,可能隐藏实际上增加了C ++程序员“惊喜”的数量。
关于这个问题的详细讨论可以在这里find…
我不知道原来的理由,但是因为藏起来或不藏起来都是差不多的select。 函数,我猜测的基本原理是有统一的规则 :在嵌套的花括号范围内定义的名称相同。
隐藏在某些方面帮助你。
将方法添加到基类将默认不会影响派生类的重载parsing。
而且你不会因为一些不正确的指令而导致你的调用失败,从而void*
带有forms参数void*
的基类方法。 这样的事情。
干杯&hth。,
我确定我已经看到了这个由C ++大佬提供的情况,不知道是哪个:
struct Base { void f(const Base&); }; struct Derived : Base { using Base::f; void f(double); }; int main() { Derived d; df('a'); // calls Derived::f }
现在,添加void f(int);
到Base
,和主要变化的意义 – 它调用Base::f
因为int
是char
更好的匹配 – 这是一个整数推广,而不是一个标准的转换。
目前还不清楚这种改变是否真的被程序员用char
来捕获,所以要求using
明确的意思是默认的行为是这个改变不会影响调用代码。 我相信这只是一个边际的呼吁,但我认为委员会认为C ++中的基类已经足够脆弱了,没有这些:-)
没有必要使用“隐藏”关键字,因为在Derived中没有重载“f”的情况下,没有可比性的情况。
顺便说一句,我已经select了types, char
故意不协调。 你可以用int
和unsigned int
来获得更微妙的情况,而不是int
和char
。
隐藏基类的成员函数(具有相同名称但签名不同)的另一个原因可能是由可选参数引起的歧义。 考虑下面的例子:
#include <stdio.h> class A { public: int foo(int a, int b=0) { printf("in A : %d, %d\n", a, b); } }; class B : public A { public: int foo(int a) { printf("in B : %d\n", a); foo(a); //B:foo(a) will be called unless we explicitly call A:foo(a) foo(a, 1); // compile error: no matching function for call to B:foo(int&, int) } }; int main() { B b; b.foo(10); return 0; }
如果基类中的foo
方法没有被隐藏起来,那么编译器就不可能决定是否应该调用A::foo
或者是B::foo
因为以下代码行与两个签名都匹配:
foo(a);
可能的原因是模板专业化。 我举个例子:
template <int D> struct A { void f() }; template <> struct A<1> { void f(int) }; template <int D> struct B: A<D> { void g() { this->f(); } };
模板类B有一个方法f()
,但是直到你不创build类B的实例,你不知道签名。 所以调用this->f()
是随时“合法”的 。 在创build实例之前,GCC和CLang都不报告错误。 但是,当您调用B<1>
实例的方法g()
,它们会指示错误。 所以隐藏规则保持简单,以检查你的代码是否有效。
我报告在我的例子中使用的代码的最后一部分。
int main (int argc, char const *argv[]) { B<0> b0; /* valid */ B<1> b1; /* valid */ b0.g(); /* valid */ b1.g(); /* error: no matching function for call to 'B<1>::f()' */ return 0; }