假设我在C++中,并且我有这个伪接口(interface)(只有abstract classpure virtual methods):

class IErrorLog
{
public:
    virtual bool closeLog() = 0;
};

class FileErrorLog : public IErrorLog
{
public:
    FileErrorLog(){}
    ~FileErrorLog(){}

    bool closeLog() {
        std::cout << "Close FileErrorLog" << std::endl;
        return true;
    }
};

int main()
{
    FileErrorLog fileErrorLog;
    IErrorLog *log = &fileErrorLog;
    log->closeLog();
}

对于I've learned而言,使用动态类型closeLogIErrorLog被称为去虚拟化vtable的那个FileErrorLog并选择所需的目标函数(closeLog()指针)。

由于在C#中的interfaces并不是真正的类,因此当我执行以下操作时:
interface IErrorLog {
    void closeLog ();
}

public class FileErrorLog : IErrorLog
{
    public FileErrorLog() {}

    public void closeLog() {
        Console.WriteLine("Close FileErrorLog");
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        IErrorLog log = new FileErrorLog();
        log.closeLog();
    }
}

C#将如何解析closeLog()?是相同的机制吗?

因为这里IErrorLog log不再是abstract class。它是本机类型。因此,我不认为logFileErrorLog的指针。

你能跟我解释一下吗?

最佳答案



运行时将通过使用实现定义的机制来正确解析调用。

在接口(interface)的情况下,此机制非常复杂,并且会对性能产生有趣的影响。



它与某些C++编译器用于不同类型系统的机制是否相同?几乎可以肯定不是。

但是,机制是相似的,因为有函数指针表卡在对象实例指针上,并且在运行时进行查找以进行方法分派(dispatch)。



我假设您的意思是“托管指针”;在C#中,我们希望您将引用表征为“引用”;非托管指针非常不同。

由于托管指针不同是错误的,因此您有一个错误的信念。您从错误信念得出的任何结论都是不合理推理的结果,并且不可靠。

根据您的问题和大量评论,您的核心错误信念似乎是对对象的引用的内存表示形式取决于用于存储引用的变量的类型。 这种信念完全是100%错误的,所以现在就停止相信。在CLR中,引用转换是保留表示的转换。

如果用数字0x12345678表示对类类型C的对象的引用,然后将其转换为对用C实现的接口(interface)I的引用,则表示形式仍为0x12345678。



该站点不建议使用教程。

10-01 08:00
查看更多