import std.stdio; import std.conv; class first{ int func(int x){ return x; } int func(double x){ return to!(int)(x+0.5); } } class second : first{ override int func(int x){ return x/2; } } unittest{ second blah = new second(); writeln(blah.func(4.5)); }
请注意,在第一个类中,“func”被重载,并且该类第二个会覆盖采用int的func版本,但不会覆盖采用double的版本.
此代码无法编译,并显示一条消息,表明func(double)未被继承:
tmp.d(24): Error: function tmp.second.func (int x) is not callable using argument types (double)
但是,如果我从类“second”中删除重写函数,则继承func(double).在这之后,代码编译并按预期运行.
删除对非继承的重载函数tmp.func(4.5)的调用会产生不同的编译错误:
tmp.d(15): Deprecation: class tmp.second use of tmp.first.func(double x) hidden by second is deprecated. Use 'alias first.func func;' to introduce base class overload set.
它似乎建议我应该将first.func的别名声明为第二个func,实际上,将该别名添加到类“second”允许代码进行编译.
虽然这解决了这个问题,但我对D为何以这种方式实现有点神秘.这让我有两个问题:
1.如果重载函数没有被覆盖,为什么会自动继承,但如果其中一个被覆盖则不会继承?
2.有没有办法在没有这种别名的情况下覆盖其中一个重载的成员函数?
这是为了防止功能劫持: http://dlang.org/hijack.html从历史上看,在C程序中存在各种有趣的问题,你没有调用你想要调用的函数,并且通过强制程序员明确地将所有函数的重载带到派生类范围,它迫使程序员确保调用它们期望调用的重载,而不是仅仅因为隐式转换的工作原理而调用基类实现.所以,虽然它可能有点烦人,但它有助于防止细微的错误.
如果要控制派生类中的哪些重载,那么您将必须单独声明每个重载.如果将基类’重载别名为派生类’作用域,则会获得所有重载.从语法上讲,没有办法告诉编译器你想要使用该特定符号名称为某些函数设置别名.所有你能做的就是给出符号名称,所以它是全有或全无.但是通过在派生类中声明你想要的每个重载(如果你不想改变它们的行为,每个都使用super来调用基类版本),那么你可以控制你拥有的那些.是的,这有点单调乏味,但不幸的是,这就是它的方式.
但它并不像显式别名,每个重载都会更加冗长.如果它是合法的,它可能会是这样的
alias foo = bool X.foo(int a, float b) const;
(其中X是基类的名称)而不是
bool foo(int a, float b) const { return super(a, b); }
所以,我不认为添加别名特定重载的能力真的会给你带来太大的影响.