【发布时间】:2018-03-11 18:16:11
【问题描述】:
假设我在C++,我有这个伪接口(@987654325@,只有pure 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、closeLog,使用动态类型IErrorLog,称为将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。它是原生类型。因此,我不认为log 是指向FileErrorLog 的指针。
你能给我解释一下吗?
【问题讨论】:
-
仅仅因为您通过
IErrorLog引用log并不能使其成为实际类型。实际上它仍然是FileErrorLog。 IIRC C# 在 C++ 中使用相同的 vtable 设计。 -
@SombreroChicken 我认为 c# 设计有点不同。考虑到在
FileErrorLog中,您可以同时实现closeLog和IErrorLog.CloseLog(如果我没记错的话,后者将在OP 场景中调用) -
这是旧方法的入门指南.NET Framework Internals - Interface Vtable Map and Interface Map。这个模型在virtual stub dispatch 中发生了相当大的变化,但显示了“旧式”的 vtable 接口调度。