首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我要为匿名类“需要opCmp”?

为什么我要为匿名类“需要opCmp”?
EN

Stack Overflow用户
提问于 2012-03-17 18:00:46
回答 1查看 339关注 0票数 3

我不太清楚该如何解释,所以请让我澄清任何不合理的事情。我有一个接口和一个模板函数,它返回基于编译时参数返回匿名内部类的函数:

代码语言:javascript
复制
interface MyInterface {
    void getName();
}
MyInterface function() getMyInterfaceFactory(string name)() {
    return function() {
        return new class MyInterface {
            void getName() { //Do something involving name here }
        };
    };
}

现在,getMyInterfaceFactory()过去是getMyInterface(),过去它直接返回匿名对象。一切都很好。当我添加工厂函数时,我开始从Object获得启动期间的异常:

代码语言:javascript
复制
object.Exception.....(102): need opCmp for class mymodule.getMyInterfaceFactory!("someargument").getMyInterfaceFactory.__funcliteral14.__anonclass13

因此,我查看了醉酒时源中的抛出行,它看起来就像对象抛出的opCmp的默认实现。我没有在任何地方比较工厂函数或MyInterface。我将工厂存储为字符串索引关联数组的值,但当我将匿名类直接存储在该数组中时,只在开始存储函数时,不需要opCmp。如果我插入一个opCmp (使用内存地址),一切似乎都正常工作,但MyInterface并不是真正的可比,所以除非我必须这样做,否则我宁愿不这样做。如果可能的话,我想知道为什么/在匿名类上调用opCmp,以及如何防止或处理它。

注意:对象中opCmp的默认实现包括一个模糊引用bug的注释、一个注释掉的内存地址比较,然后是抛出的版本。

谢谢!

编辑:我应该提到,我尝试了windbg和ddbg来精确地找到调用opCmp的位置,但在这两种情况下都失败了。Windbg没有提供任何有用的信息,因为它顽固地拒绝加载任何符号,却在初始化期间(在静态模块构造函数之后,在main之前)发生异常,并且假定ddbg无法访问醉酒时间符号?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-19 18:45:36

更新:在玩具示例中,我在复制opCmp错误时遇到了困难,但我想我已经弄清楚了发生了什么。

似乎创建匿名内部类来继承匿名函数内部的接口是错误的(go图)。具体来说,匿名类在虚拟函数方面表现不佳。即使定义了opCmp,我在toString和默认构造函数中也有错误,而且成员什么也不做(但是调用时不要抛出或错误)。__traits(allMembers, MyInterface)__traits(allMembers, typeof(anonInstance))一样返回预期的信息,但是经常调用列出的成员不起作用。真奇怪。

但是,如果我用抽象方法将接口更改为类,则解析opCmp错误,匿名类按预期的方式工作,等等。我不太了解编译器,但我认为在编译过程中构建了一个符号表,该表将虚拟函数名映射到存储在vtbl中的内存地址。我认为,在返回从接口派生的匿名类时,生成的映射是不同的。这是可能的,因为接口支持多重继承,因此不能指定绝对的vtbl映射。但是,类可能要求所有继承者都坚持相同的映射方案(我不知道它们是否坚持,但它们可以),这样匿名类就不会以不同的映射结束。

再次,我真的不确定,但它似乎符合症状,opCmp被调用,即使我没有使用它的任何地方。我不认为opCmp才是问题所在,我认为对象中定义的所有虚拟函数都是脆弱的。我能够通过以下几点来支持这一点:

代码语言:javascript
复制
testopcmphelper.d
interface TestInterface {
    string helloWorld();
}
class TestClass {
    abstract string helloWorld();
}

testopcmp.d
import testopcmphelper;
import std.stdio;

void invokeFn(TestInterface function() f) {
    auto t = f();
    auto s = t.helloWorld();
    writeln(s);
}

unittest {
    auto f = function() {
        return new class TestInterface {
            string helloWorld() {
                return "Hello World!";
            }
        };
    };
    invokeFn(f);
}

void invokeFn(TestClass function() f) {
    auto t = f();
    auto s = t.helloWorld();
    writeln(s);
}

unittest {
    auto f = function() {
        return new class TestClass {
            string helloWorld() {
                return "Goodbye World!";
            }
        };
    };
    invokeFn(f);
}

其中的指纹:

代码语言:javascript
复制
src.utilities.testopcmp.__unittest2.__funcliteral1.__anonclass10
Goodbye World!

指示invokeFn(TestInterface)正在调用Object.toString而不是TestInterface.helloWorld

我打算把这个问题留到另一天,以防我弄错了。然后我可能会将此报告为DMD中的一个bug。我将通过只对匿名工厂函数基类型使用抽象类来解决这个问题。TL;DR似乎是一种虫。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9752414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档