You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:23:16