在D语言中能否覆盖类的非函数成员?虚表vtable仅含函数指针吗?
在D语言中覆盖非函数类成员的问题
首先直接给结论:D语言的类虚表(vtable)只包含函数指针,非函数类型的类成员(比如你代码里的字符串s)是无法被派生类覆盖的。你当前的代码里,Bar类中的s只是隐藏了基类Foo的同名成员,而非真正意义上的覆盖。
为什么你的代码输出"foo"而不是"bar"呢?当你用基类类型的引用Foo bar = new Bar访问s时,D编译器会根据变量的静态类型(也就是Foo)来解析成员,所以它会直接访问Foo类中定义的s,完全不会考虑实际指向的Bar对象里的那个s。
要实现你想要的输出"bar"的效果,你需要把成员变量包装成虚函数(或者带@property的虚属性方法),让它能通过虚表进行动态调度。比如这样修改代码:
class Foo { private string _s = "foo"; @property virtual string s() { return _s; } } class Bar : Foo { private string _s = "bar"; @property override string s() { return _s; } } void main() { import std.stdio; Foo bar = new Bar; writeln(bar.s); // 现在会输出"bar" }
这里用@property装饰器是为了让我们能像访问普通成员变量一样调用这个方法(不用加括号),更符合你原本的代码习惯。如果不需要这种语法,直接用普通的虚函数也可以:
class Foo { private string _s = "foo"; virtual string getS() { return _s; } } class Bar : Foo { private string _s = "bar"; override string getS() { return _s; } } void main() { import std.stdio; Foo bar = new Bar; writeln(bar.getS()); // 输出"bar" }
简单总结一下:在D语言中,只有虚函数支持派生类的覆盖操作,成员变量只能被同名的派生类成员隐藏,无法实现动态的覆盖效果。如果需要类似“覆盖成员变量”的行为,通过虚属性方法来间接实现是标准的解决方案。
内容的提问来源于stack exchange,提问作者michaelmeyer
相关产品推荐
相关产品推荐

