当前位置:  开发笔记 > 编程语言 > 正文

食人族课程

如何解决《食人族课程》经验,为你挑选了3个好方法。

有一段时间以来,我一直试图解决为什么允许一些"食人族"类编译的原因.

在我继续之前,也许我应该解释一下我称之为"食人族"的课程.不确定我是刚刚发明了这个术语,还是已经存在了一段时间,或者即使我正确使用它,但现在这并不重要.

我基本上把食人族叫做一个消耗自己的类.换句话说,一个类的接口声明了自己类型的成员.例如:

class Foo
{
    public Foo SomeFoo; 
}

如上所示,类Foo有一个类型为Foo(本身)的成员.

现在,我第一次看到这个(很久以前)我没有编译它的东西,但令我惊讶的是它确实编译了.我之所以没有编译的原因,是因为对我来说,这会尖叫某种类型的递归噩梦.

为了使事情进一步复杂化,我决定尝试同样的事情,但使类成为一个结构,如:

struct Foo
{
    public Foo SomeFoo; 
}

不幸的是,这不会编译,而是你得到错误:类型'Foo'的struct成员'Foo.SomeFoo'导致struct布局中的循环

对我来说,编译错误更有意义,没有错误,但我相信这种行为最合乎逻辑的解释,所以我想知道你们中是否有人可以解释这种行为.

谢谢.



1> mqp..:

你不能设计这样的结构的原因是因为结构必须在分配一些默认值时被初始化.所以,当你有一个Foo像你所描述的结构,并创建一个Foo...

Foo x; // x = default(Foo)

它调用默认构造函数Foo.但是,该默认构造函数必须为该Foo.SomeFoo字段提供默认值.

那么,它是如何找到的?它必须打电话default(Foo).其中,为了构建一个Foo,必须为该Foo.SomeFoo字段赋予默认值......正如你猜测的那样,这是一个递归的噩梦.

既然你可以创建一个类的空引用,并且不要立即实际创建该类的实例,那就没问题了; 你可以打电话new Foo(),Foo.SomeFoo只会是空的.不需要递归.

附录:当你想到这个时,如果你仍然感到困惑,我认为其他答案有另一个好的方法来考虑它(同样的基本问题,不同的方法) - 当程序为a分配内存时Foo,它是怎么回事去做吧?什么sizeof(Foo)时候Foo包含一些东西,然后是另一个整体Foo?你不能这样做.

相反,如果它是一个类,它只需要为一个引用分配几个字节Foo,而不是实际Foo,并且没有问题.



2> Denis Trolle..:

不同之处在于Foo是一种参考类型.类内存布局将有一个指向Foo实例的指针,这样就可以了.

在结构的情况下,你基本上有一个无限的recusrsive内存布局,无法工作.

现在,如果你的类试图在它自己的构造函数中实例化一个Foo,那么你将遇到Stack溢出问题.



3> MarkusQ..:

它们被称为递归类型,它们很常见.例如,树通常根据引用其他节点的"节点"来实现.没有什么是矛盾的,只要它们互相引用但彼此不相互包含.

作为绕过它的一种方法,整数的平方总是另一个整数.没有什么奇怪的,它只是两个整数之间的引用或关系.但是你不能拥有一个包含自身完整副本的字符串作为子字符串.这就是区别.

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有