<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>司维的思维</title>
	<atom:link href="http://wei.si/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://wei.si/blog</link>
	<description>思维比较活跃所以老换地方</description>
	<lastBuildDate>Wed, 11 Apr 2012 07:40:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>新坑</title>
		<link>http://wei.si/blog/2012/04/sgf-viewer-on-windows-phone/</link>
		<comments>http://wei.si/blog/2012/04/sgf-viewer-on-windows-phone/#comments</comments>
		<pubDate>Wed, 11 Apr 2012 07:39:16 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643614</guid>
		<description><![CDATA[Windows Phone上打谱软件的坑挖好了，正在犹豫是否要跳填。
SGF解析部分来自于Super Go。昨天改掉了一些问题，但更大问题是Super Go实际上是对战类型，这个SGF解析只有最简单的功能。而作为打谱软件，要具备以下功能才行：
1.标记，例如下面这些（图片来自于http://senseis.xmp.net/?HowDiagramsWork）：

2.分支。在棋局、死活题、变化等讲解时非常有用。
3.交互。做题时候可以根据落子不同进行解说。就像EidoGo那样。
4.棋谱库。维护棋谱，并可以做出修改。
简而言之就是尽量多支持sgf的Tag。另外本来想直接沿用Super Go的各种数据结构，但一来为了支持上面这些功能，二来如果都用了人家的自己就写点UI算什么？所以重写ing。现在大概就是这样：

如果决定填坑的话，保守估计一个月的业余时间要搭进去。
p.s：著名的XGoo（在移动平台的知名度不亚于Stonebase之于PC）最近出了iOS版本！这是个值得让人去买个pad的软件，不夸张。
]]></description>
			<content:encoded><![CDATA[<p>Windows Phone上打谱软件的坑挖好了，正在犹豫是否要<del datetime="2012-04-11T07:17:00+00:00">跳</del>填。</p>
<p>SGF解析部分来自于<a href="http://supergo.codeplex.com/">Super Go</a>。昨天改掉了一些问题，但更大问题是Super Go实际上是对战类型，这个SGF解析只有最简单的功能。而作为打谱软件，要具备以下功能才行：</p>
<p>1.标记，例如下面这些（图片来自于<a href="http://senseis.xmp.net/?HowDiagramsWork">http://senseis.xmp.net/?HowDiagramsWork</a>）：<br />
<a href="http://wei.si/blog/wp-content/uploads/2012/04/marks-in-sgf.png"><img src="http://wei.si/blog/index.php?feedimage=wp-content/uploads/2012/04/marks-in-sgf.png" alt="" title="marks in sgf" width="128" height="105" class="aligncenter size-full wp-image-643616" /></a><br />
2.分支。在棋局、死活题、变化等讲解时非常有用。<br />
3.交互。做题时候可以根据落子不同进行解说。就像<a href="http://eidogo.com">EidoGo</a>那样。<br />
4.棋谱库。维护棋谱，并可以做出修改。</p>
<p>简而言之就是尽量多支持sgf的Tag。另外本来想直接沿用Super Go的各种数据结构，但一来为了支持上面这些功能，二来如果都用了人家的自己就写点UI算什么？所以重写ing。现在大概就是这样：</p>
<p><a href="http://wei.si/blog/wp-content/uploads/2012/04/Mango.jpg"><img src="http://wei.si/blog/index.php?feedimage=wp-content/uploads/2012/04/Mango-180x300.jpg" alt="" title="sgf viewer" width="180" height="300" class="aligncenter size-medium wp-image-643615" /></a></p>
<p>如果决定填坑的话，保守估计一个月的业余时间要搭进去。</p>
<p>p.s：著名的XGoo（在移动平台的知名度不亚于Stonebase之于PC）<a href="http://itunes.apple.com/us/app/xgoo-hd/id508416256?mt=8">最近出了iOS版本</a>！这是个值得让人去买个pad的软件，不夸张。</p>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/04/sgf-viewer-on-windows-phone/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>试一下EidoGo插件</title>
		<link>http://wei.si/blog/2012/04/try-eidogo-plugin/</link>
		<comments>http://wei.si/blog/2012/04/try-eidogo-plugin/#comments</comments>
		<pubDate>Sun, 01 Apr 2012 05:27:30 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[体育]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643608</guid>
		<description><![CDATA[<br />
<b>Warning</b>:  escapeshellarg() has been disabled for security reasons in <b>/home/weisi/domains/wei.si/public_html/blog/wp-content/plugins/eidogo-for-wordpress/wp-eidogo.php</b> on line <b>1082</b><br />
<br />
<b>Warning</b>:  escapeshellarg() has been disabled for security reasons in <b>/home/weisi/domains/wei.si/public_html/blog/wp-content/plugins/eidogo-for-wordpress/wp-eidogo.php</b> on line <b>1089</b><br />
<br />
<b>Warning</b>:  proc_open() has been disabled for security reasons in <b>/home/weisi/domains/wei.si/public_html/blog/wp-content/plugins/eidogo-for-wordpress/wp-eidogo.php</b> on line <b>1097</b><br />
竟然还有wordpress专用插件，太高级了。
[Embedded SGF File: “迷你中国流” 布局浅析]
]]></description>
			<content:encoded><![CDATA[<br />
<b>Warning</b>:  escapeshellarg() has been disabled for security reasons in <b>/home/weisi/domains/wei.si/public_html/blog/wp-content/plugins/eidogo-for-wordpress/wp-eidogo.php</b> on line <b>1082</b><br />
<br />
<b>Warning</b>:  escapeshellarg() has been disabled for security reasons in <b>/home/weisi/domains/wei.si/public_html/blog/wp-content/plugins/eidogo-for-wordpress/wp-eidogo.php</b> on line <b>1089</b><br />
<br />
<b>Warning</b>:  proc_open() has been disabled for security reasons in <b>/home/weisi/domains/wei.si/public_html/blog/wp-content/plugins/eidogo-for-wordpress/wp-eidogo.php</b> on line <b>1097</b><br />
<p>竟然还有wordpress专用插件，太高级了。</p>
<p>[Embedded SGF File: “迷你中国流” 布局浅析]</p>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/04/try-eidogo-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>让AudioPlayerAgent支持动态播放列表（Windows Phone）</title>
		<link>http://wei.si/blog/2012/03/dynamic-play-list-for-audioplayeragent/</link>
		<comments>http://wei.si/blog/2012/03/dynamic-play-list-for-audioplayeragent/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 07:25:30 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643604</guid>
		<description><![CDATA[最近做的是有关背景音乐播放（调用系统播放器）的活儿，其中牵扯到Microsoft.Phone.BackgroundAudio.BackgroundAudioPlayer播放本地或远程音频时候的播放列表改动问题。如果希望播放系统Music + Videos中存储的音乐，那么直接在UI利用Microsoft.Xna.Framework.Media传递和播放音乐即可。但如果是BackgroundAudioPlayer和AudioPlayerAgent就不太好办。
可能有人会说这种问题还用得着单写一篇文章吗，AudioPlayerAgent当然支持动态列表了。但很可惜MSDN的官方How-To的例子就是硬编码的列表（还是本地音频），不然也不会在App Hub Forum上出现这样的问题（1、2）。
一般来说将播放列表传递给Agent有这几种方式：

IsolatedStorageSettings
静态方法或属性（作为BackgroundAgent，实例化它没有意义）
IsolatedStorageFile

实验之后就会发现，前两种方法并不好用：虽然在UI线程中设置了列表或者通过静态方法、属性传递了列表，但启动后的Agent拿不到这些数据。就算是单写一个存储播放列表数据的静态类也是一样。那么留给我们的方法只有通过文件传递。
在上面提到的那个帖子中，一位微软员工Mark Chamberlain给出的方案也是如此（全文请看原帖）：
This is how I did it:
In background audio agent code:
OnUserAction.Play/SkipNext/SkipPrevious: Check if BackgroundAudioPlayer.Instance.Track == null, if yes then load playlist from IsoStorage into m_playlist and start playing first track, if no then play current/next/previous song from m_playlist
In the album viewmodel code (each time a user selects an album a new [...]]]></description>
			<content:encoded><![CDATA[<p>最近做的是有关背景音乐播放（调用系统播放器）的活儿，其中牵扯到Microsoft.Phone.BackgroundAudio.BackgroundAudioPlayer播放本地或远程音频时候的播放列表改动问题。如果希望播放系统Music + Videos中存储的音乐，那么直接在UI利用Microsoft.Xna.Framework.Media传递和播放音乐即可。但如果是BackgroundAudioPlayer和AudioPlayerAgent就不太好办。</p>
<p>可能有人会说这种问题还用得着单写一篇文章吗，AudioPlayerAgent当然支持动态列表了。但很可惜MSDN的<a href="http://msdn.microsoft.com/en-us/library/hh202978(v=VS.92).aspx">官方How-To的例子</a>就是硬编码的列表（还是本地音频），不然也不会在App Hub Forum上出现这样的问题（<a href="http://forums.create.msdn.com/forums/t/88429.aspx">1</a>、<a href="http://forums.create.msdn.com/forums/p/86769/521287.aspx">2</a>）。</p>
<p>一般来说将播放列表传递给Agent有这几种方式：</p>
<ul>
<li>IsolatedStorageSettings</li>
<li>静态方法或属性（作为BackgroundAgent，实例化它没有意义）</li>
<li>IsolatedStorageFile</li>
</ul>
<p>实验之后就会发现，前两种方法并不好用：虽然在UI线程中设置了列表或者通过静态方法、属性传递了列表，但启动后的Agent拿不到这些数据。就算是单写一个存储播放列表数据的静态类也是一样。那么留给我们的方法只有通过文件传递。</p>
<p>在<a href="http://forums.create.msdn.com/forums/t/88429.aspx">上面提到的那个帖子中</a>，一位微软员工Mark Chamberlain给出的方案也是如此（全文请看原帖）：</p>
<blockquote><p>This is how I did it:<br />
In background audio agent code:<br />
OnUserAction.Play/SkipNext/SkipPrevious: Check if BackgroundAudioPlayer.Instance.Track == null, if yes then load playlist from IsoStorage into m_playlist and start playing first track, if no then play current/next/previous song from m_playlist<br />
In the album viewmodel code (each time a user selects an album a new viewmodel gets created for this app):<br />
OnInitialization:&#8230;<br />
Another developer who reviewed this suggested that instead of calling ..Instance.Close(), which also releases all the background audio resources, a better approach is to set BackgroundAudioPlayer.Instance.Track = null, which stops and clears, but keeps the background resources allocated.</p></blockquote>
<p>基本思路即UI存好文件，Agent初始化时候载入。任何和播放相关操作前播放列表如果为null则再次载入。</p>
<p>具体到我手头的例子，文件格式我直接用的Xml序列化，写起来简单。由于需要和UI保持实时，那么每修改一次播放列表（添加、删除、改动）都要保存，同时在Agent一边，任何和播放相关操作前则不仅检查是否列表为null，而是直接全部重新载入。类似于：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> OnUserAction<span style="color: #000000;">&#40;</span>BackgroundAudioPlayer player, AudioTrack track, UserAction action, <span style="color: #FF0000;">object</span> param<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    var allTracks <span style="color: #008000;">=</span> TrackManager.<span style="color: #0000FF;">GetAllTracks</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    _playList <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>AudioTrack<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span> TrackItem trackItem <span style="color: #0600FF;">in</span> allTracks <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    _playList.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span> 
            <span style="color: #008000;">new</span> AudioTrack<span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">null</span>, trackItem.<span style="color: #0000FF;">Title</span>, trackItem.<span style="color: #0000FF;">Album</span>, <span style="color: #0600FF;">null</span>, <span style="color: #0600FF;">null</span>, trackItem.<span style="color: #0000FF;">Url</span>, EnabledPlayerControls.<span style="color: #0000FF;">Pause</span> <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #008080; font-style: italic;">//...</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>代码写出来非常愚蠢，但目前为止找不到更好的方法。</p>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/03/dynamic-play-list-for-audioplayeragent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>有关dynamic_cast的可用性（基础差害死人）</title>
		<link>http://wei.si/blog/2012/03/about-dynamic_cast/</link>
		<comments>http://wei.si/blog/2012/03/about-dynamic_cast/#comments</comments>
		<pubDate>Mon, 26 Mar 2012 05:48:40 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643592</guid>
		<description><![CDATA[一直以来，有关dynamic_cast&#60;&#62;这个转换所读到的书和材料消化后，都觉得结论是“拥有带有继承关系的对象指针转换，安全，会抛异常”。但事实上真的如此吗？看下面的代码：

class B1&#123;virtual void foo&#40;&#41;&#123;&#125;&#125;;
class B2&#123;&#125;;
class D&#123;&#125;;
D* pD=dynamic_cast&#60;D*&#62;&#40;new B1&#40;&#41;&#41;; // （1）
cout&#60;&#60;*&#40;int*&#41;&#40;&#38;pD&#41;&#60;&#60;endl;
D* pD2=dynamic_cast&#60;D*&#62;&#40;new B2&#40;&#41;&#41;; // （2）
cout&#60;&#60;*&#40;int*&#41;&#40;&#38;pD2&#41;&#60;&#60;endl;

可以看到B1、B2和D三个类没什么继承关系，但（1）处通过编译，（2）处提示：
cannot dynamic_cast `(((main()::B2*)operator new(1u)), (((*)  main()::B2()), ))' (of type `class main()::B2*') to type `class main()::D*' (source type is not polymorphic) 
即来源类型非多态。所以实际上并非是“有继承关系的对象指针”可用dynamic_cast&#60;&#62;转换，而是有vtable的类都可以转——只不过没继承关系的话转出来为NULL。
那么再想一下，既然提示了“多态”，也就是说关键点不在“继承”这里，所以形如下面的代码：

class X &#123;&#125;;
class Y : X &#123;&#125;;
Y* y = dynamic_cast&#60;Y*&#62;&#40;new X&#40;&#41;&#41;; // failed!

虽然两个类有继承关系，但必然通不过编译，因为基类子类并未表现出多态，编译器不会多费劲来生成vtable。在文章多继承的虚指针中提到了dynamic_cast的内部实现：

void *FindCompleteObject &#40;void *ptr &#41;
&#123;
     [...]]]></description>
			<content:encoded><![CDATA[<p>一直以来，有关dynamic_cast&lt;&gt;这个转换所读到的书和材料消化后，都觉得结论是“拥有带有继承关系的对象指针转换，安全，会抛异常”。但事实上真的如此吗？看下面的代码：</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> B1<span style="color: #008000;">&#123;</span><span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> B2<span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> D<span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
D<span style="color: #000040;">*</span> pD<span style="color: #000080;">=</span><span style="color: #0000ff;">dynamic_cast</span><span style="color: #000080;">&lt;</span>D<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">new</span> B1<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// （1）</span>
<span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span><span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>pD<span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
D<span style="color: #000040;">*</span> pD2<span style="color: #000080;">=</span><span style="color: #0000ff;">dynamic_cast</span><span style="color: #000080;">&lt;</span>D<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">new</span> B2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// （2）</span>
<span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span><span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>pD2<span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span></pre></div></div>

<p>可以看到B1、B2和D三个类没什么继承关系，但（1）处通过编译，（2）处提示：</p>
<pre>cannot dynamic_cast `(((main()::B2*)operator new(1u)), (((*<anonymous>) <unknown operator> main()::B2()), <anonymous>))' (of type `class main()::B2*') to type `class main()::D*' (source type is not polymorphic) </pre>
<p>即来源类型非多态。所以实际上并非是“有继承关系的对象指针”可用dynamic_cast&lt;&gt;转换，而是有vtable的类都可以转——只不过没继承关系的话转出来为NULL。<br />
那么再想一下，既然提示了“多态”，也就是说关键点不在“继承”这里，所以形如下面的代码：</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> X <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Y <span style="color: #008080;">:</span> X <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
Y<span style="color: #000040;">*</span> y <span style="color: #000080;">=</span> <span style="color: #0000ff;">dynamic_cast</span><span style="color: #000080;">&lt;</span>Y<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">new</span> X<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// failed!</span></pre></div></div>

<p>虽然两个类有继承关系，但必然通不过编译，因为基类子类并未表现出多态，编译器不会多费劲来生成vtable。在文章<a href="http://blog.csdn.net/lw02nju/article/details/4528510">多继承的虚指针</a>中提到了dynamic_cast<void*>的内部实现：</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span>FindCompleteObject <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span>ptr <span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
     <span style="color: #0000ff;">const</span> _s_RTTICompleteObjectLocator <span style="color: #000040;">*</span>pCompleteLocator <span style="color: #000080;">=</span>GetCompleteObjectLocator <span style="color: #008000;">&#40;</span>ptr <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
     ptr <span style="color: #000080;">=</span>ptr <span style="color: #000040;">-</span>pCompleteLocator <span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>offset <span style="color: #008080;">;</span>
     <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pCompleteLocator <span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>cdOffset <span style="color: #008000;">&#41;</span> ptr <span style="color: #000040;">-</span><span style="color: #000080;">=</span><span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span>ptr <span style="color: #000040;">-</span>pCompleteLocator <span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>cdOffset <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
     <span style="color: #0000ff;">return</span> ptr <span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span>__RTCastToVoid <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span>ptr <span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
     <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>ptr <span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span> <span style="color: #008080;">;</span>
     <span style="color: #0000ff;">return</span> FindCompleteObject <span style="color: #008000;">&#40;</span>ptr <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>可以看到只有vtable存在，寻找Complete Object Locator的行为才有意义——虚表的第一项就是RTTI Complete Object Locator（RTTI Info），其中包含RTTI类型描述（Type Descriptor）、RTTI继承关系（Class Hierarchy）<sup>[2]</sup>。故言C++的RTTI特性也是以vtable的存在为基础，没有虚函数或其他virtual特性，RTTI不生效。<br />
当然一般使用中其实理解成dynamic_cast&lt;&gt;用于向下转换带有继承关系的指针也没错，上面提到的这两个特例应该很少会出现在实际代码中吧。但此处犯错足见俺基础太差，离C++对象模型的深入理解还差得远。<br />
p.s：真想把之前这类因为基础差犯2B错误的文章集结起来。最近几个月就写了不少。</p>
<h2>参考资料</h2>
<ol>
<li><a href="http://blog.csdn.net/lw02nju/article/details/4528510">多继承的虚指针</a>，lw02nju</li>
<li><a href="http://www.cnblogs.com/zhyg6516/archive/2011/03/07/1971898.html" target="_blank">浅议 Dynamic_cast 和 RTTI</a>，RocZhang</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/03/about-dynamic_cast/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Objective-C学习笔记（4-7）</title>
		<link>http://wei.si/blog/2012/02/objective-c-study-notes-4-7/</link>
		<comments>http://wei.si/blog/2012/02/objective-c-study-notes-4-7/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 05:14:24 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643586</guid>
		<description><![CDATA[目录

构造和拷贝构造
动态特性和RTTI
内存管理和标准C区别
监视方式
数据持久化
RTTI和动态特性2
容器类、Block和NSPredicate

04监视方式
Protocol
用protocol实现的delegate。其实我觉得这个就是观察者，只不过默认情况下是单一的观察者。具体方法不总结了。
有什么方法可以一次性存放多个delegate？这样就可以用数组方法一口气通知完：

&#91;array makeObjectsPerformSelector:@selector&#40;doSomething:&#41; withObject:aObject&#93;;

如果写N个变量第一比较罗嗦第二也不知道运行时会有多少个观察者。但问题在于NSArray和NSMutableArray不能存指针之外的对象，protocol实例不认。
KVO
KVO，也就是Key-Value Observer，是除了protocol和notification之外的又一种属性监视方式
监视别人的类重载一个方法，用于观察值变化

- &#40;void&#41; observeValueForKeyPath:&#40;NSString*&#41;aPath ofObject:&#40;id&#41;anObject change:&#40;NSDictionary*&#41;aChange context:&#40;void*&#41;aContext &#123;
           NSLog&#40; @&#34;%@ has observered key %@ change in %@, from %@ to %@&#34;,
                &#91;self class&#93;, aPath, anObject, &#91;aChange objectForKey:@&#34;old&#34;&#93;, &#91;aChange objectForKey:@&#34;new&#34;&#93; &#41;;
&#125;

被监视的类不用特意修改。
发送消息时，需要用NSObject里面某Category已经定义好的add/removeObserver增删observer即可

Coder* me = [...]]]></description>
			<content:encoded><![CDATA[<h2>目录</h2>
<ol>
<li><a href="http://wei.si/blog/2012/01/objective-c-study-notes-1-3/#chap01">构造和拷贝构造</a></li>
<li><a href="http://wei.si/blog/2012/01/objective-c-study-notes-1-3/#chap02">动态特性和RTTI</a></li>
<li><a href="http://wei.si/blog/2012/01/objective-c-study-notes-1-3/#chap03">内存管理和标准C区别</a></li>
<li><a href="#chap04">监视方式</a></li>
<li><a href="#chap05">数据持久化</a></li>
<li><a href="#chap06">RTTI和动态特性2</a></li>
<li><a href="#chap07">容器类、Block和NSPredicate</a></li>
</ol>
<h2 id="chap04">04监视方式</h2>
<p>Protocol</p>
<p>用protocol实现的delegate。其实我觉得这个就是观察者，只不过默认情况下是单一的观察者。具体方法不总结了。</p>
<p>有什么方法可以一次性存放多个delegate？这样就可以用数组方法一口气通知完：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>array makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>doSomething<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span>aObject<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>如果写N个变量第一比较罗嗦第二也不知道运行时会有多少个观察者。但问题在于NSArray和NSMutableArray不能存指针之外的对象，protocol实例不认。</p>
<h3>KVO</h3>
<p>KVO，也就是Key-Value Observer，是除了protocol和notification之外的又一种属性监视方式</p>
<p>监视别人的类重载一个方法，用于观察值变化</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> observeValueForKeyPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aPath ofObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>anObject change<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aChange context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aContext <span style="color: #002200;">&#123;</span>
           NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@ has observered key %@ change in %@, from %@ to %@&quot;</span>,
                <span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span>, aPath, anObject, <span style="color: #002200;">&#91;</span>aChange objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;old&quot;</span><span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>aChange objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;new&quot;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>被监视的类不用特意修改。</p>
<p>发送消息时，需要用NSObject里面某Category已经定义好的add/removeObserver增删observer即可</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Coder<span style="color: #002200;">*</span> me <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>me setLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;C#&quot;</span><span style="color: #002200;">&#93;</span>;
    Computer<span style="color: #002200;">*</span> computer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Computer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer addObserver<span style="color: #002200;">:</span>me forKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;workload&quot;</span> options<span style="color: #002200;">:</span>NSKeyValueObservingOptionNew | NSKeyValueObservingOptionNew context<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer setWorkload<span style="color: #002200;">:</span><span style="color: #2400d9;">10</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer setWorkload<span style="color: #002200;">:</span><span style="color: #2400d9;">50</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer removeObserver<span style="color: #002200;">:</span>me forKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;workload&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer release<span style="color: #002200;">&#93;</span>;&lt;span <span style="color: #a61390;">id</span><span style="color: #002200;">=</span><span style="color: #bf1d1a;">&quot;more-643586&quot;</span>&gt;&lt;<span style="color: #002200;">/</span>span&gt;</pre></div></div>

<h3>Notification Center</h3>
<p>监视者在初始化时候告诉NC自己要监视“哪个名字”，这个名字可以自定，只要保证post消息时候用一样的即可。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSNotificationCenter</span><span style="color: #002200;">*</span> notifyCenter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNotificationCenter</span> defaultCenter<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>notifyCenter addObserver<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleWorkloadNotification<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> name<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;workload_notify&quot;</span> object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>需要传入一个方法的selector。具体函数名参数名随便，但参数只能有一个NSNotification。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> handleWorkloadNotification<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSNotification</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aNotification <span style="color: #002200;">&#123;</span>
    Computer<span style="color: #002200;">*</span> newCom <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>aNotification object<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@ has been notified with workload %d from %@&quot;</span>, <span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>newCom workload<span style="color: #002200;">&#93;</span>, newCom <span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>被监视的类不用特意修改。</p>
<p>发送通知时，使用NC的postNotificationName方法，这里的name就是上面那个。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Coder<span style="color: #002200;">*</span> me <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Coder alloc<span style="color: #002200;">&#93;</span> initWithArgs<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span> andLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;C#&quot;</span><span style="color: #002200;">&#93;</span>;
    Computer<span style="color: #002200;">*</span> computer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Computer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSNotificationCenter</span><span style="color: #002200;">*</span> notifyCenter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNotificationCenter</span> defaultCenter<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>notifyCenter postNotificationName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;workload_notify&quot;</span> object<span style="color: #002200;">:</span>computer<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer setWorkload<span style="color: #002200;">:</span><span style="color: #2400d9;">10</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>notifyCenter postNotificationName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;workload_notify&quot;</span> object<span style="color: #002200;">:</span>computer<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>me release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>computer release<span style="color: #002200;">&#93;</span>;</pre></div></div>

<h2 id="chap05">05数据持久化</h2>
<h3>plist</h3>
<p>plist文件用于存储程序相关的一些内容，类似于ini文件或者.Net下面的app.config。NSData、NSArray和NSDictionary可以直接用xxxWithContentsOfFile和writeToFile读写：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Coder<span style="color: #002200;">*</span> siw <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>siw setLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;C#&quot;</span><span style="color: #002200;">&#93;</span>;
    Coder<span style="color: #002200;">*</span> yexd <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ye Xiaodong&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>yexd setLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Objective-C&quot;</span><span style="color: #002200;">&#93;</span>;
    Person<span style="color: #002200;">*</span> nan_zhang <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Zhang Nan&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">29</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span>siw, yexd, nan_zhang, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs writeToFile<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pdata1.txt&quot;</span> atomically<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs writeToFile<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pdata1_a.txt&quot;</span> atomically<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_fromFile <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithContentsOfFile<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pdata1.txt&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">//[(Coder*)[objs_fromFile objectAtIndex:0] ShowInfo]; // 不过这样不行的……</span></pre></div></div>

<p>上面最后一行肯定不行，因为拿出来的是GSMutableString，可以打开存储的文件看看。序列化后的应该是XML，不过在windows上就是逗号分隔数据了。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#40;</span>
    <span style="color: #bf1d1a;">&quot;&amp;lt;Coder: 0xd4d1a0&amp;gt;&quot;</span>,
    <span style="color: #bf1d1a;">&quot;&amp;lt;Coder: 0xd712c0&amp;gt;&quot;</span>,
    <span style="color: #bf1d1a;">&quot;&amp;lt;Person: 0xd44be0&amp;gt;&quot;</span>
<span style="color: #002200;">&#41;</span></pre></div></div>

<p>如果希望将存储有自定义类的array或者dictionary持久化的话，可以想到的方案是实现下面NSCoding的方法，塞到array后给再下面说的NSUserDefault。</p>
<p><a name="archiver"></a></p>
<h3>archiver</h3>
<p>archiver以二进制方式存储数据。需要存储的类要实现两个定义在NSCoding协议里面的方法：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> encodeWithCoder<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> coder <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;encoding: %@&quot;</span>, self <span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>coder encodeObject<span style="color: #002200;">:</span> name forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder encodeInt<span style="color: #002200;">:</span> age forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pid&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithCoder<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decoder <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;decoding: %@&quot;</span>, self <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self initWithArgs<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>decoder decodeObjectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span> andAge<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>decoder decodeIntForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;age&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>initWithCoder里面我用了自己实现的构造函数。默认情况下和init一样用[super init]再赋值也OK。注意用的时候归档和读档的类是不同的：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSKeyedArchiver</span> archivedDataWithRootObject<span style="color: #002200;">:</span>siw<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>data writeToFile<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;siwei.data&quot;</span> atomically<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSData</span><span style="color: #002200;">*</span> data_fromArchive <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithContentsOfFile<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;siwei.data&quot;</span><span style="color: #002200;">&#93;</span>;
    Coder<span style="color: #002200;">*</span> siw_fromArchive <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSKeyedUnarchiver</span> unarchiveObjectWithData<span style="color: #002200;">:</span>data_fromArchive<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>siw_fromArchive ShowInfo<span style="color: #002200;">&#93;</span>;</pre></div></div>

<h3>UD</h3>
<p>User Defaults类似于全局字典，访问数据更灵活：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSUserDefaults</span><span style="color: #002200;">*</span> userDefaults <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSUserDefaults</span> standardUserDefaults<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>userDefaults setObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;siwei&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;me&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">//[userDefaults setObject:objs forKey:@&quot;objs&quot;];</span>
    <span style="color: #002200;">&#91;</span>userDefaults setInteger<span style="color: #002200;">:</span><span style="color: #2400d9;">42</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;int&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>userDefaults synchronize<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>这样就存储完了。最后一句不必要。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_fromUD <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>userDefaults objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;objs&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>objs_fromUD count<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>objs_fromUD objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span> respondsToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>GetInfo<span style="color: #002200;">:</span>TheSecondArg<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;array: %@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>objs_fromUD objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">100</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span>userDefaults objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;me&quot;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d&quot;</span>, <span style="color: #002200;">&#91;</span>userDefaults integerForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;int&quot;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>读取数据如上所示。不过在GNUStep上面不能把array给setObject到UD里面去，提示Argument Exception。按理说所有内置plist类型都是没问题的。</p>
<p><a name="SQL"></a></p>
<h3>SQL</h3>
<p>Sqlite持久化实现了传说中的ORM，适用于数据量比较大的情况。并且有第三方的开源项目进一步简化操作 <a title="http://code.google.com/p/sqlitepersistentobjects/" rel="nofollow" href="http://code.google.com/p/sqlitepersistentobjects/" target="_blank">Sqlist Persistent Objects</a>。</p>
<h3>Core Data</h3>
<p>Core Data是基于Model、Entity和Relationship的存储方式，利用sql语句直接访问持久化文件，通过各种和数据库概念相对应的类——例如NSEntityDescription对应表结构、NSFetchRequest对应查询等——实现对数据库的封装，免得去写SQL语句。不过实现起来复杂到恶心，不愧是企业级应用。有兴趣可以看看<a title="http://www.notsoso.im/index.php/tag/core-data/" rel="nofollow" href="http://www.notsoso.im/index.php/tag/core-data/" target="_blank">教程@notsos.im</a>。</p>
<h2 id="chap06">06RTTI和动态特性2</h2>
<h3>isa指针</h3>
<p>所有NSObject继承下来的对象都有一个isa指针，指向具体的Class定义，所以所有从一个类实例化出来的对象的isa指针都一样。看一下NSObject指针就能看出来，这个指针指向的是objc_class类型。所以id实际上就是一个指向指向objc_class指针的指针。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> <span style="color: #400080;">NSObject</span> <span style="color: #002200;">&amp;</span>lt;NSObject<span style="color: #002200;">&amp;</span>gt; <span style="color: #002200;">&#123;</span>
   <span style="color: #a61390;">Class</span>       isa;
&nbsp;
<span style="color: #a61390;">typedef</span> <span style="color: #a61390;">struct</span> objc_class <span style="color: #002200;">*</span><span style="color: #a61390;">Class</span>;
<span style="color: #a61390;">typedef</span> <span style="color: #a61390;">struct</span> objc_object <span style="color: #002200;">&#123;</span>
   <span style="color: #a61390;">Class</span> isa;
<span style="color: #002200;">&#125;</span> <span style="color: #002200;">*</span><span style="color: #a61390;">id</span>;
...</pre></div></div>

<p>对于[class method]的调用，都会变成obj_msgSend这个函数的调用，看下面的函数原型可以知道，调用方法的时候，receiver的isa指针会首先被使用，查找SEL对象是否存在。如果不存在，就继续用当前Class对象的isa指针查找父类的SEL定义中是否有需要的，直到NSObject为止。如果都没有的话就抛一个NSInvalidArgument异常（见过最多的……）。</p>
<p><a name="obj_msgSend"></a></p>
<h3>obj_msgSend</h3>
<p>原型为objc_msgSend(id receiver,SEL selector,参数…)</p>
<p>继续沿着上面说的方法调用中的isa指针查找来看，如果找到了SEL的定义，那么拿到receiver的self指针进行SEL的调用，当然参数要传过去。</p>
<h3>动态方法</h3>
<p>obj-c 2.0里面引入了@property、@syncthesize指令方便地声明属性。对于仍然需要自定义setter/getter的属性来说可以用@dynamic指定。除了手动写之外，还可以在运行时指定</p>
<p>其实就是重写一个class method，将传入的SEL动态设定为setter或者getter</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// 声明一个函数，用来动态添加。前两个参数不能变——因为要转换成IMP类型</span>
<span style="color: #a61390;">void</span> dynamicMethod<span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> self,<span style="color: #a61390;">SEL</span> _cmd,<span style="color: #a61390;">float</span> w<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
  &lt;a href<span style="color: #002200;">=</span><span style="color: #bf1d1a;">&quot;http://www.opengroup.org/onlinepubs/009695399/functions/printf.html&quot;</span>&gt;printf&lt;<span style="color: #002200;">/</span>a&gt;<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">&quot;dynamicMethod-%s<span style="color: #2400d9;">\n</span>&quot;</span>,<span style="color: #002200;">&#91;</span>NSStringFromSelector<span style="color: #002200;">&#40;</span>_cmd<span style="color: #002200;">&#41;</span>
cStringUsingEncoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
  &lt;a href<span style="color: #002200;">=</span><span style="color: #bf1d1a;">&quot;http://www.opengroup.org/onlinepubs/009695399/functions/printf.html&quot;</span>&gt;printf&lt;<span style="color: #002200;">/</span>a&gt;<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">&quot;%f<span style="color: #2400d9;">\n</span>&quot;</span>,w<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// 类方法</span>
<span style="color: #002200;">+</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> resolveInstanceMethod<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span> sel<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>methodName<span style="color: #002200;">=</span>NSStringFromSelector<span style="color: #002200;">&#40;</span>sel<span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">BOOL</span> result<span style="color: #002200;">=</span><span style="color: #a61390;">NO</span>;
<span style="color: #11740a; font-style: italic;">// 检查SEL的名字是必要的，因为只有符合命名规则的函数才可以用</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>methodName isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;setHeight:&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
   class_addMethod<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span>, sel, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">IMP</span><span style="color: #002200;">&#41;</span> dynamicMethod,
                  <span style="color: #bf1d1a;">&quot;v@:f&quot;</span><span style="color: #002200;">&#41;</span>;
  result<span style="color: #002200;">=</span><span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
  <span style="color: #a61390;">return</span> result;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>注意class_addMethod最后一个参数，这是函数签名的简单表示。v=void, @=id, :=SEL, f=float，要根据实际函数定义进行更改。</p>
<p>这段在apple的文档中<a title="http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html" rel="nofollow" href="http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html" target="_blank">也专门有一篇文章</a>，不过写得晦涩到让人不得不觉得是故意让人看不懂。</p>
<h3>有关self</h3>
<p>Instance method里面的self是当前对象的首地址；Class method里面的则是Class指针，也就是isa。</p>
<p>下面语句位于Coder类的init方法中，会打印出来什么？第一反应肯定是Coder, Person。但实际上都是Coder……因为obj-c的消息机制是会不停地寻找父类方法。最后virtual到子类上。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@, %@&quot;</span>, <span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>super class<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<h3>Method类型</h3>
<p>定义，可以看到Method类型是SEL和IMP的合体成果</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">typedef</span> <span style="color: #a61390;">struct</span> objc_method <span style="color: #002200;">*</span>Method;
<span style="color: #a61390;">struct</span> objc_method <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">SEL</span> method_name;
  <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span>method_types;
  <span style="color: #a61390;">IMP</span> method_imp;
<span style="color: #002200;">&#125;</span>;</pre></div></div>

<p>动态替换方法，既然METHOD是struct，就可以直接用-&gt;访问它的成员了，例如在Coder类里面可以用父类Person的某个方法替换自己的：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">SEL</span> selGetInfo <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>GetInfo<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>;
    Method myMethod <span style="color: #002200;">=</span> class_getInstanceMethod<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span>, selGetInfo<span style="color: #002200;">&#41;</span>;
    Method baseMethod <span style="color: #002200;">=</span> class_getInstanceMethod<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>Person class<span style="color: #002200;">&#93;</span>, selGetInfo<span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">// 不过10.5之后就拿不到method_imp了</span>
   myMethod<span style="color: #002200;">-&amp;</span>gt;method_imp <span style="color: #002200;">=</span>baseMethod<span style="color: #002200;">-&amp;</span>gt;method_imp;</pre></div></div>

<h2 id="chap07">07容器类、Block和NSPredicate</h2>
<h3>NS(Mutable)Array</h3>
<p>遍历队列中对象的方法，使用makeObjectsPerformSelector。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Coder<span style="color: #002200;">*</span> siw <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>siw setLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;C#&quot;</span><span style="color: #002200;">&#93;</span>;
    Coder<span style="color: #002200;">*</span> yexd <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ye Xiaodong&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>yexd setLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Objective-C&quot;</span><span style="color: #002200;">&#93;</span>;
    Person<span style="color: #002200;">*</span> nan_zhang <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Zhang Nan&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">29</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span>siw, yexd, nan_zhang, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>GetInfo<span style="color: #002200;">:</span>TheSecondArg<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><span style="color: #2400d9;">10</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// GetInfo有两个参数，而且返回一个NSString*</span>
    <span style="color: #002200;">&#91;</span>objs makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ShowInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>不过比较郁闷的是这个方法不能返回值，也不能使用一个以上的参数调用SEL。如果需要返回值或者传入多个参数，还是要用NSInvocation。</p>
<p>writeToFile方法的第二个参数atomically，表示的是是否采用原子操作。即如果参数为YES，那么写入文件时候先写入临时文件，完成后覆盖所要真正写入的文件。这样可以避免写入过程中系统出现问题导致文件损坏。</p>
<p>NSArray也支持切片操作，不过语法太不灵活了——或者说obj-c中所有容器类的访问语法都太罗嗦。连续的元素切片用subarrayWithRange，不连续的用objectsAtIndexes</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// 连续</span>
    <span style="color: #a61390;">NSRange</span> range;
    range.location <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
    range.length <span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_new <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs subarrayWithRange<span style="color: #002200;">:</span>range<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs_new makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ShowInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// 不连续</span>
    <span style="color: #400080;">NSMutableIndexSet</span><span style="color: #002200;">*</span> indices <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableIndexSet</span> indexSet<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>indices addIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>indices addIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_fromIndex <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs objectsAtIndexes<span style="color: #002200;">:</span>indices<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs_fromIndex makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ShowInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>排序操作，NSArray提供了N个方法，按照所利用的排序参数，简单可以分为descriptor、selector、function和block排序</p>
<h3>function排序</h3>
<p>需要实现一个签名为NSInteger (*)(id, id, void *)的方法</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSInteger mySortByAge<span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> o1, <span style="color: #a61390;">id</span> o2, <span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>context<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">int</span> v1 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>Person<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>o1 age<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">int</span> v2 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>Person<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>o2 age<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>v1 <span style="color: #002200;">&amp;</span>lt; v2<span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> NSOrderedAscending;
    <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>v1 <span style="color: #002200;">&amp;</span>gt; v2<span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> NSOrderedDescending;
    <span style="color: #a61390;">else</span>
        <span style="color: #a61390;">return</span> NSOrderedSame;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>使用的时候把指针传进去就行了</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_sortedByFunction <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs sortedArrayUsingFunction<span style="color: #002200;">:</span>mySortByAge context<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs_sortedByFunction makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ShowInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<h3>selector排序</h3>
<p>需要排序的类要实现一个方法，传入一个和自身类型相同的参数，同self进行自定义比较。NSString的例子看下面的应用，在NSSortDescriptor初始化的时候传入了xxxCompare方法作为具体的比较方法，而其他内置类也都实现了compare方法，例如NSNumber就可以用compare方法的SEL。对于自己的类则需要实现一个方法，返回NSComparisonResult（其实就是NSInteger，枚举），要声明，因为不是继承来的。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSComparisonResult<span style="color: #002200;">&#41;</span> ageCompare<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> rhsPerson <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">int</span> v1 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self age<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">int</span> v2 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>Person<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>rhsPerson age<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>v1 <span style="color: #002200;">&amp;</span>lt; v2<span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> NSOrderedAscending;
    <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>v1 <span style="color: #002200;">&amp;</span>gt; v2<span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> NSOrderedDescending;
    <span style="color: #a61390;">else</span>
        <span style="color: #a61390;">return</span> NSOrderedSame;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>使用和function没什么区别，只不过参数是SEL而已。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_sortedBySelector <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs sortedArrayUsingSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ageCompare<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs_sortedBySelector makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ShowInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<h3>descriptor排序</h3>
<p>是一种比较特殊的包含比较信息的类，主要用于自定义类型的排序。需要指定按照什么key——也就是property进行排序，以及具体的排序算法（selector）和排序选项（例如是否倒序等）。看一下代码就清楚了</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSSortDescriptor</span> <span style="color: #002200;">*</span>sortDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSSortDescriptor</span> alloc<span style="color: #002200;">&#93;</span> initWithKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span> ascending<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span>               selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>localizedCaseInsensitiveCompare<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_sortedByDescriptor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs sortedArrayUsingDescriptors<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span>sortDesc, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">//NSArray* descriptors = [NSSortDescriptor sortDescriptorWithKey:@&quot;name&quot; ascending:NO];</span>
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_sortedByDescriptor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs sortedArrayUsingDescriptors<span style="color: #002200;">:</span>descriptors<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>objs_sortedByDescriptor makeObjectsPerformSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>ShowInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>block需要特别记录一下，所以分出一个条目。</p>
<p><a name="Block"></a></p>
<h3>Block</h3>
<p>数组排序时候有个sortedArrayUsingComparator方法，这里的参数类型为NSComparator。这个类其实就是Block所定义的</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">typedef</span> NSComparisonResult <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span>NSComparator<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> obj1, <span style="color: #a61390;">id</span> obj2<span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>所以我们可以直接</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSComparator myComparator <span style="color: #002200;">=</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> obj1, <span style="color: #a61390;">id</span> obj2<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span><span style="color: #002200;">&#125;</span><span style="color: #002200;">:</span></pre></div></div>

<p>NSArray中还有指明要使用Block的方法，例如- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block</p>
<p>Block其实可以看作JS里面的(){}();方法以及.Net中的匿名方法，即不需要声明就直接使用的方法，主要用处包括回调、事件处理和排序。声明和实现可以像上面的NSComparator一样分开，也可以写在一起：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSInteger <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span>blockExample<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span>, <span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span> <span style="color: #a61390;">int</span> i, <span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> s <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d, %@&quot;</span>, i, s <span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>;
    blockExample<span style="color: #002200;">&#40;</span> <span style="color: #2400d9;">42</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;hello&quot;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>对于NSArray的排序（或者其他需要Block作为参数的函数）来说，可以写成下面两种形式：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// 声明和使用</span>
NSComparison <span style="color: #002200;">&#40;</span> <span style="color: #002200;">^</span>ageComparator <span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span> <span style="color: #a61390;">id</span>, <span style="color: #a61390;">id</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span> <span style="color: #a61390;">id</span> o1, <span style="color: #a61390;">id</span> o2 <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// 比较函数的实现</span>
<span style="color: #002200;">&#125;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_sortedByComparator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs sortedArrayUsingComparator<span style="color: #002200;">:</span>ageComparator<span style="color: #002200;">&#93;</span>;
<span style="color: #11740a; font-style: italic;">// 不声明，彻底匿名使用</span>
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_sortedByComparator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs sortedArrayUsingComparator<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span> <span style="color: #a61390;">id</span> o1, <span style="color: #a61390;">id</span> o2 <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span> <span style="color: #11740a; font-style: italic;">//...</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>枚举一个容器则可以类似于：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>tmpArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>timeZoneNames objectsAtIndexes<span style="color: #002200;">:</span>areaIndexes<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>tmpArray enumerateObjectsWithOptions<span style="color: #002200;">:</span>NSEnumerationConcurrent|NSEnumerationReverse
                           usingBlock<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> obj, NSUInteger idx, <span style="color: #a61390;">BOOL</span> <span style="color: #002200;">*</span>stop<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                               <span style="color: #002200;">&#91;</span>areaArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>obj substringFromIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>area length<span style="color: #002200;">&#93;</span><span style="color: #002200;">+</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>实际上可以看作是obj-c里面闭包的最好例子。更多可以看<a title="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html" rel="nofollow" href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html" target="_blank">http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html</a></p>
<h3>NS(Mutable)Dictionary</h3>
<p>基本的操作，例如初始化、插入、删除、查找等，不说了。</p>
<p>排序也不说了，其实就相当于将keys提取成NSArray进行排序。</p>
<p>那还有啥可说的呢……比如自定义的排序key。默认情况下只能使用NSString，但自定义类也可以当作hash key使用，需要实现下面这两项内容。实际情况中需要自定义key的场合非常少。<br />
NSCopying协议。将key/value加入字典时候，系统实际上会拷贝一份key使用。所以copyWithZone必须实现。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">hash<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>和isEqual<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>方法。这两个方法用于生成项目的hash值，以及比较两个对象的hash值。
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span> hash<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">return</span> pid<span style="color: #002200;">+</span><span style="color: #002200;">&#91;</span>name hash<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> isEqual<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> p<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>pid<span style="color: #002200;">==</span><span style="color: #002200;">&#91;</span>p pid<span style="color: #002200;">&#93;</span><span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&#91;</span>name isEqualToString<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>p name<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>     <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
  <span style="color: #002200;">&#125;</span><span style="color: #a61390;">else</span><span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<h3>MapTable</h3>
<p>感觉上和NSMutableDictionary很像，也是根据key进行1-1对应的容器，也可以增删元素。但它不一样的地方在于内部是弱引用的。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSPointerFunctionsOptions keyOptions<span style="color: #002200;">=</span>NSPointerFunctionsStrongMemory |
        NSPointerFunctionsObjectPersonality | NSPointerFunctionsCopyIn;
    NSPointerFunctionsOptions valueOptions<span style="color: #002200;">=</span>NSPointerFunctionsOpaqueMemory |
        NSPointerFunctionsOpaquePersonality;
    <span style="color: #400080;">NSMapTable</span><span style="color: #002200;">*</span> mapTable<span style="color: #002200;">=</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMapTable</span> mapTableWithKeyOptions<span style="color: #002200;">:</span> keyOptions valueOptions<span style="color: #002200;">:</span>valueOptions<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> key1 <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;siwei&quot;</span>;
    NSMapInsert<span style="color: #002200;">&#40;</span> mapTable, key1, siw <span style="color: #002200;">&#41;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@, %@&quot;</span>, <span style="color: #002200;">*</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>NSMapGet<span style="color: #002200;">&#40;</span> mapTable, key1 <span style="color: #002200;">&#41;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>Coder<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>NSMapGet<span style="color: #002200;">&#40;</span> mapTable, key1 <span style="color: #002200;">&#41;</span> language<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d&quot;</span>, <span style="color: #002200;">&#91;</span>siw retainCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;  <span style="color: #11740a; font-style: italic;">// 1</span></pre></div></div>

<p>而其他内置容器类基本都是强引用</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span>siw, yexd, nan_zhang, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d&quot;</span>, <span style="color: #002200;">&#91;</span>siw retainCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;  <span style="color: #11740a; font-style: italic;">// 2</span>
    <span style="color: #400080;">NSDictionary</span><span style="color: #002200;">*</span> dict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>siw, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;siwei&quot;</span>, yexd, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ye Xiaodong&quot;</span>, nan_zhang, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Zhang Nan&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d&quot;</span>, <span style="color: #002200;">&#91;</span>siw retainCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;  <span style="color: #11740a; font-style: italic;">// 3</span></pre></div></div>

<h3>NS(Mutable)Set</h3>
<p>Set里面的元素是无序排列且无key的。初始化和array一样，也可以直接用initWithArray从array创建。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSSet</span><span style="color: #002200;">*</span> set <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSSet</span> setWithObjects<span style="color: #002200;">:</span>siw, yexd, nan_zhang, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d&quot;</span>, <span style="color: #002200;">&#91;</span>siw retainCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;  <span style="color: #11740a; font-style: italic;">// 2</span></pre></div></div>

<p>和Dictionary一样，Set也有对应的弱引用容器类，就叫Hash Table</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSHashTable</span><span style="color: #002200;">*</span> hashTable<span style="color: #002200;">=</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSHashTable</span> alloc<span style="color: #002200;">&#93;</span> initWithOptions<span style="color: #002200;">:</span>
    NSPointerFunctionsOpaqueMemory |NSPointerFunctionsOpaquePersonality
    capacity<span style="color: #002200;">:</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
    NSHashInsert<span style="color: #002200;">&#40;</span> hashTable, siw <span style="color: #002200;">&#41;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d&quot;</span>, <span style="color: #002200;">&#91;</span>siw retainCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;  <span style="color: #11740a; font-style: italic;">// 1</span></pre></div></div>

<h3>NSPredicate</h3>
<p>这东西用起来有点像.Net的LINQ，是根据条件从集合里面筛选数据的语法糖。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSPredicate</span><span style="color: #002200;">*</span> predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;age &amp;gt; 28&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>objs count<span style="color: #002200;">&#93;</span>; <span style="color: #002200;">++</span>i <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>predicate evaluateWithObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>objs objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>objs objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span></pre></div></div>

<p>可以使用的运算符包括AND、OR、NOT、BETWEEN、IN、LIKE等</p>
<p>模板</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSPredicate</span><span style="color: #002200;">*</span> templatePredicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name == $NAME&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSDictionary</span><span style="color: #002200;">*</span> dict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NAME&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSPredicate</span> <span style="color: #002200;">*</span>pre<span style="color: #002200;">=</span><span style="color: #002200;">&#91;</span>templatePredicate predicateWithSubstitutionVariables<span style="color: #002200;">:</span> dict<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">//NSPredicate* predicate = [NSPredicate predicateWithFormat:@&quot;age &amp;gt; 28&quot;];</span>
    <span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>objs count<span style="color: #002200;">&#93;</span>; <span style="color: #002200;">++</span>i <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>templatePredicate evaluateWithObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>objs objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>objs objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span></pre></div></div>

<p>其实上面Array里面切片方法也应该包括这个NSPredicate，因为它可以用来筛选array元素</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSPredicate</span><span style="color: #002200;">*</span> predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;age &amp;gt; 28&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_filtered <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs filteredArrayUsingPredicate<span style="color: #002200;">:</span> predicate<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>objs_filtered objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>字符串运算</p>
<ul>
<li>BEGINWITH, ENDWITH, CONTAINS</li>
<li>c和d分别表示大小写不敏感和重音符号不敏感，例如如果是&#8221;name BEGINWITH[d]&#8216;e&#8217;&#8221;的话，那么“étudent&#8221;这样的词也会符合条件</li>
</ul>
<p>LIKE结合?和*可以进行通配符匹配</p>
<p>正则表达式</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> regex <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;^S.+i$&quot;</span>;
    <span style="color: #400080;">NSPredicate</span><span style="color: #002200;">*</span> regexPredicate<span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name MATCHES %@&quot;</span>, regex<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> objs_filtered <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>objs filteredArrayUsingPredicate<span style="color: #002200;">:</span>regexPredicate<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>objs_filtered objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<h3>容器类的深浅拷贝</h3>
<p>默认情况下用一个容器去初始化另外一个容器是浅拷贝，也就是说只是retain里面的引用而已</p>
<p>可能的深拷贝，用重载的initWithArray:copyItems:YES。不过之所以说这是“可能的”，是因为容器里面的对象不一定实现了NSCopying协议！如果没有实现的话，对于对象本身的拷贝还是浅拷贝。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>deepCopyArray<span style="color: #002200;">=</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> alloc<span style="color: #002200;">&#93;</span> initWithArray<span style="color: #002200;">:</span> someArray copyItems<span style="color: #002200;">:</span> <span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>真正的深拷贝，需要用到NSKeyedArchiver。但需要的时间和空间开销必然陡增。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span> trueDeepCopyArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSKeyedUnarchiver</span> unarchiveObjectWithData<span style="color: #002200;">:</span>
          <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSKeyedArchiver</span> archivedDataWithRootObject<span style="color: #002200;">:</span> oldArray<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/02/objective-c-study-notes-4-7/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PS Vita上手两周总结</title>
		<link>http://wei.si/blog/2012/01/ps-vita/</link>
		<comments>http://wei.si/blog/2012/01/ps-vita/#comments</comments>
		<pubDate>Sat, 28 Jan 2012 04:00:25 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643580</guid>
		<description><![CDATA[临放假前和同事以及哥们一起买了PS Vita准备欢度龙年，裸机+8G卡=￥2390，略贵，但便宜的美版还要一个月，等不起。
回来后就升级到了最新版本软件（两次，够频繁的），游戏也及时升级了，没出现过死机现象。
和之前在网上预先看到的相同，屏幕、机能的改进不是一星半点。主屏上的图标有明显的马赛克，后来仔细一看是3D模型造成的，屏幕本身就算屏气凝神也几乎看不到像素点的边界。既然屏幕大了，必然整体尺寸比PSP大了不少：

游戏方面不锁区确实很好。《神秘海域》值得入手，画面效果和游戏时间综合来看性价比不错。《三国无双NEXT》卖得也太贵了，1.5G的游戏容量，而且只有一条故事线原来是还没玩通的缘故，本作依然有光荣最喜欢的架空历史，虽然把刷各种奖杯的时间算上能延长不少游戏时间，但整体来说比《神海》还贵的价格真是让人觉得诧异。《天启之王》的手感不错，游戏方式类似于MH，如果没有人联机的话乐趣会大大减少。

PSV自带个有趣的功能NEAR，可以看到附近的玩家和热门游戏，例如我周围方圆1公里范围内有60多个人在玩（这么多？今天已经74了）。

总体体验非常好，掌机的未来还会是“专一”功能的。如果玩了3DS和PSV，还有人鼓吹手机游戏是便携型类型游戏的未来，那真的只能笑而不语了。
]]></description>
			<content:encoded><![CDATA[<p>临放假前和同事以及哥们一起买了PS Vita准备欢度龙年，裸机+8G卡=￥2390，略贵，但便宜的美版还要一个月，等不起。</p>
<p>回来后就升级到了最新版本软件（两次，够频繁的），游戏也及时升级了，没出现过死机现象。</p>
<p>和之前在网上预先看到的相同，屏幕、机能的改进不是一星半点。主屏上的图标有明显的马赛克，后来仔细一看是3D模型造成的，屏幕本身就算屏气凝神也几乎看不到像素点的边界。既然屏幕大了，必然整体尺寸比PSP大了不少：</p>
<p><a href="http://wei.si/blog/wp-content/uploads/2012/01/WP_000115.jpg"><img class="aligncenter size-medium wp-image-643581" title="WP_000115" src="http://wei.si/blog/index.php?feedimage=wp-content/uploads/2012/01/WP_000115-300x224.jpg" alt="" width="300" height="224" /></a></p>
<p>游戏方面不锁区确实很好。《神秘海域》值得入手，画面效果和游戏时间综合来看性价比不错。《三国无双NEXT》卖得也太贵了，1.5G的游戏容量，<span style="text-decoration: line-through;"><span style="color: #c0c0c0;">而且只有一条故事线</span></span>原来是还没玩通的缘故，本作依然有光荣最喜欢的架空历史，虽然把刷各种奖杯的时间算上能延长不少游戏时间，但整体来说比《神海》还贵的价格真是让人觉得诧异。《天启之王》的手感不错，游戏方式类似于MH，如果没有人联机的话乐趣会大大减少。</p>
<p><a href="http://wei.si/blog/wp-content/uploads/2012/01/2012-01-22-143952.jpg"><img class="aligncenter size-medium wp-image-643582" title="2012-01-22-143952" src="http://wei.si/blog/index.php?feedimage=wp-content/uploads/2012/01/2012-01-22-143952-300x170.jpg" alt="" width="300" height="170" /></a></p>
<p>PSV自带个有趣的功能NEAR，可以看到附近的玩家和热门游戏，例如我周围方圆1公里范围内有60多个人在玩（这么多？今天已经74了）。</p>
<p><a href="http://wei.si/blog/wp-content/uploads/2012/01/2012-01-22-220218.jpg"><img class="aligncenter size-medium wp-image-643583" title="2012-01-22-220218" src="http://wei.si/blog/index.php?feedimage=wp-content/uploads/2012/01/2012-01-22-220218-300x170.jpg" alt="" width="300" height="170" /></a></p>
<p>总体体验非常好，掌机的未来还会是“专一”功能的。如果玩了3DS和PSV，还有人鼓吹手机游戏是便携型类型游戏的未来，那真的只能笑而不语了。</p>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/01/ps-vita/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>微软的Playful Programming？？</title>
		<link>http://wei.si/blog/2012/01/playful-programming-from-microsoft/</link>
		<comments>http://wei.si/blog/2012/01/playful-programming-from-microsoft/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 02:51:40 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643578</guid>
		<description><![CDATA[这几天在刷PSV奖杯，结果看到这么个东西：微软的Visual Studio Achievements扩展。

作用就是在程序员完成一些“成就”后给予提示和记录，获取相应的称号。例如：

在一个类里面声明100个成员变量（Field Master）
一行代码写300个字符（Scroll Bar Wizard）
使用“Close All But This”10次（Obsessive Compulsive Disorder）
……

看来以后可以加班刷成就啦！
]]></description>
			<content:encoded><![CDATA[<p>这几天在刷PSV奖杯，结果看到这么个东西：<a href="http://channel9.msdn.com/achievements/visualstudio" target="_blank">微软的Visual Studio Achievements扩展</a>。</p>
<p style="text-align: center;"><img class="aligncenter" src="http://channel9.msdn.com/styles/images/achievements/VSscreenshot1.png" alt="" width="368" height="221" /></p>
<p>作用就是在程序员完成一些“成就”后给予提示和记录，获取相应的称号。例如：</p>
<ul>
<li>在一个类里面声明100个成员变量（Field Master）</li>
<li>一行代码写300个字符（Scroll Bar Wizard）</li>
<li>使用“Close All But This”10次（Obsessive Compulsive Disorder）</li>
<li>……</li>
</ul>
<p>看来以后可以加班刷成就啦！</p>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/01/playful-programming-from-microsoft/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Objective-C学习笔记（1-3）</title>
		<link>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/</link>
		<comments>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 08:49:17 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643570</guid>
		<description><![CDATA[去年因为项目需要临时学了一段时间Objective-C，可惜直到现在都适应不了这门语言。学习过程中根据不同主题记了一些东西下来，发出来共享，但愿能帮到一些同为入门菜鸟的Objective-C学习者，不过笔记中肯定有错，这个我比较有自知之明。笔记中的所有时间表达（昨天、这段时间）都不以现在为准，因为是好几个月之前写下的。
目录

构造和拷贝构造
动态特性和RTTI
内存管理和标准C区别

01构造和拷贝构造
首先是有关构造函数
我想实现子类基类不同数量参数的构造方式，结果昨天试验了几种方法都不行。
参见下面的代码，Person是基类，实现了一个两参数的构造函数initWithArgs。子类Coder重载了这个方法，多了一个参数，试图重用基类的方法：

// person的构造函数
- &#40;id&#41; initWithArgs : &#40;NSString*&#41; aName andAge:&#40;int&#41; aAge &#123;
Person* person = &#91;&#91;Person alloc&#93; init&#93;;
&#91;person setName: aName&#93;;
&#91;person setAge: aAge&#93;;
return person;
&#125;
// coder的构造函数
- &#40;id&#41; initWithArgs : &#40;NSString*&#41; aName andAge:&#40;NSInteger&#41; aAge andLanguage:&#40;NSString*&#41;aLanguage &#123;
return ???  //这里要返回什么
&#125;

结果昨天尝试了N种方法，全都不行！

// 不行, crash!
if &#40; self = &#91;super initWithArgs:aName andAge:aAge&#93; &#41; &#123;
&#91;self setLanguage:aLanguage&#93;;
&#125;
return self;
&#160;
// 不行，没有crash，但是基类的参数name和age都设置失败
&#91;super initWithArgs:aName andAge:aAge&#93;;
&#91;self setLanguage:aLanguage&#93;;
return self;
&#160;
// 好用，但我们的基类构造函数不就没用了吗
Coder* coder = &#91;&#91;Coder alloc&#93; [...]]]></description>
			<content:encoded><![CDATA[<p>去年因为项目需要临时学了一段时间Objective-C，可惜直到现在都适应不了这门语言。学习过程中根据不同主题记了一些东西下来，发出来共享，但愿能帮到一些同为入门菜鸟的Objective-C学习者，不过笔记中肯定有错，这个我比较有自知之明。笔记中的所有时间表达（昨天、这段时间）都不以现在为准，因为是好几个月之前写下的。</p>
<h2>目录</h2>
<ol>
<li><a href="#chap01">构造和拷贝构造</a></li>
<li><a href="#chap02">动态特性和RTTI</a></li>
<li><a href="#chap03">内存管理和标准C区别</a></li>
</ol>
<h2 id="chap01">01构造和拷贝构造</h2>
<h3>首先是有关构造函数</h3>
<p>我想实现子类基类不同数量参数的构造方式，结果昨天试验了几种方法都不行。</p>
<p>参见下面的代码，Person是基类，实现了一个两参数的构造函数initWithArgs。子类Coder重载了这个方法，多了一个参数，试图重用基类的方法：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// person的构造函数</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithArgs <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> aName andAge<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> aAge <span style="color: #002200;">&#123;</span>
Person<span style="color: #002200;">*</span> person <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Person alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>person setName<span style="color: #002200;">:</span> aName<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>person setAge<span style="color: #002200;">:</span> aAge<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> person;
<span style="color: #002200;">&#125;</span>
<span style="color: #11740a; font-style: italic;">// coder的构造函数</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithArgs <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> aName andAge<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span> aAge andLanguage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aLanguage <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">return</span> ???  <span style="color: #11740a; font-style: italic;">//这里要返回什么</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>结果昨天尝试了N种方法，全都不行！</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// 不行, crash!</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super initWithArgs<span style="color: #002200;">:</span>aName andAge<span style="color: #002200;">:</span>aAge<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>self setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">return</span> self;
&nbsp;
<span style="color: #11740a; font-style: italic;">// 不行，没有crash，但是基类的参数name和age都设置失败</span>
<span style="color: #002200;">&#91;</span>super initWithArgs<span style="color: #002200;">:</span>aName andAge<span style="color: #002200;">:</span>aAge<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>self setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> self;
&nbsp;
<span style="color: #11740a; font-style: italic;">// 好用，但我们的基类构造函数不就没用了吗</span>
Coder<span style="color: #002200;">*</span> coder <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Coder alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>coder setName<span style="color: #002200;">:</span>aName<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>coder setAge<span style="color: #002200;">:</span>aAge<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>coder setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> coder;</pre></div></div>

<p>问题在于基类的构造定义，要用[self class]获取到当前self指针的类型才对</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Person<span style="color: #002200;">*</span> person <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>子类的构造函数：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Coder<span style="color: #002200;">*</span> coder <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super initWithArgs<span style="color: #002200;">:</span>aName andAge<span style="color: #002200;">:</span>aAge<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>coder setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> coder;</pre></div></div>

<p>或者用更单纯一点的调用：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>self initWithArgs<span style="color: #002200;">:</span>aName andAge<span style="color: #002200;">:</span>aAge<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> self;</pre></div></div>

<p><span id="more-643570"></span></p>
<h3>简洁构造函数</h3>
<p>类似[类名]With[参数名]这样的构造函数，也是类方法，好处在于使用者不用alloc/release操作。内部通过autorelease实现</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> personWithName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aName andAge<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>aAge <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">id</span> ret <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span> alloc<span style="color: #002200;">&#93;</span> initWithArgs<span style="color: #002200;">:</span>aName andAge<span style="color: #002200;">:</span>aAge<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>ret autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>注意到没，构造方式很像有参数构造函数，也需要用[self class]指定类型。不然子类调用的时候就会出问题。</p>
<p>使用一下：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Person<span style="color: #002200;">*</span> siwei <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span>siwei GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
Coder<span style="color: #002200;">*</span> coder <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span>coder GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<h3>拷贝构造</h3>
<h4>allocWithZone</h4>
<p>通过copy函数实现，它会调用copyWithZone，所以在NSObject为基类的类中实现这个协议即可。注意那个allocWithZone方法和刚才已经出现过两次的[self class]：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Person 类</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> copyWithZone <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSZone</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>zone <span style="color: #002200;">&#123;</span>
    Person<span style="color: #002200;">*</span> clone <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span> allocWithZone<span style="color: #002200;">:</span>zone<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>clone setName<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self name<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>clone setAge<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self age<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// 或者写成 clone-&amp;gt;age = self-&amp;gt;age;</span>
    <span style="color: #a61390;">return</span> clone;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>对于子类来说，如果父类实现了这个方法（就像上面的Person::copyWithZone），可以直接调用，省去继承而来的数据成员的拷贝操作：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Coder 类</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> copyWithZone <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSZone</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>zone <span style="color: #002200;">&#123;</span>
    Coder<span style="color: #002200;">*</span> clone <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super copyWithZone<span style="color: #002200;">:</span>zone<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>clone setLanguage<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self language<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>clone setComputer<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self computer<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// shallow copy。也可以写成clone-&amp;gt;computer = [[self computer] retain]];</span>
    <span style="color: #002200;">&#91;</span>clone setLeader<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self leader<span style="color: #002200;">&#93;</span> copyWithZone<span style="color: #002200;">:</span>zone<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;  <span style="color: #11740a; font-style: italic;">// deep copy</span>
    <span style="color: #a61390;">return</span> clone;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>值得注意的是，在上面这段代码中，用了几种不同的copy方式</p>
<ul>
<li>[clone setProperty:[self property]]; 值拷贝，适用于各种值类型以及NSString*</li>
<li>clone-&gt;computer = [[self computer] retain]]; 相当于浅拷贝，只引用一下</li>
<li>[clone setProperty:[[self property] copyWithZone:zone]]; 深拷贝，但前提是这个属性的类必须实现copy重载才行。</li>
</ul>
<p>所以下面代码的执行结果就一目了然了：coder1的leader重新setAge后，coder2的leader属性没有改变，age还是150。</p>
<p>如果在b)里面使用[clone leader:[self leader]];的话，coder2的leader属性也会随之改变。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Coder<span style="color: #002200;">*</span> coder1 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder personWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Si Wei&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder1 setLanguage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;C#&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    Person<span style="color: #002200;">*</span> leader <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Person alloc<span style="color: #002200;">&#93;</span> initWithArgs<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Leader&quot;</span> andAge<span style="color: #002200;">:</span><span style="color: #2400d9;">150</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder1 setLeader<span style="color: #002200;">:</span>leader<span style="color: #002200;">&#93;</span>;
    Computer<span style="color: #002200;">*</span> computer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Computer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder1 setComputer<span style="color: #002200;">:</span>computer<span style="color: #002200;">&#93;</span>;
&nbsp;
    Coder<span style="color: #002200;">*</span> coder2 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>coder1 copy<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>coder2 leader<span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>; <span style="color: #11740a; font-style: italic;">// Leader, 150</span>
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>coder1 leader<span style="color: #002200;">&#93;</span> setAge<span style="color: #002200;">:</span><span style="color: #2400d9;">99</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>coder2 leader<span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>; <span style="color: #11740a; font-style: italic;">// Leader, 150</span></pre></div></div>

<p>除了allocWithZone之外，还可以使用NSCopyObject()实现拷贝</p>
<h3>NSCopyObject</h3>
<p>这是二进制拷贝，也就是说对于值类型可以省去赋值的过程（当然也包括NSString*这个指针中的异类）</p>
<p>指针则需要自己进行操作，或者retain、或者赋值。假设基类多了一个指针成员：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> copyWithZone <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSZone</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>zone <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">//Person* clone = [[self class] allocWithZone:zone];</span>
    Person<span style="color: #002200;">*</span> clone <span style="color: #002200;">=</span> NSCopyObject<span style="color: #002200;">&#40;</span> self, <span style="color: #2400d9;">0</span>, zone <span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">//[clone setName:[self name]];  // 不再需要</span>
    <span style="color: #11740a; font-style: italic;">//[clone setAge:[self age]];  // 不再需要</span>
    clone<span style="color: #002200;">-&amp;</span>gt;pObject <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;  <span style="color: #11740a; font-style: italic;">// 需要，重置指针</span>
    <span style="color: #002200;">&#91;</span>clone setPObject<span style="color: #002200;">:</span>self<span style="color: #002200;">-&amp;</span>gt;pObject<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> clone;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>于子类来说，一定要知道父类的copyWithZone实现才能决定用什么方式copy：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> copyWithZone <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSZone</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>zone <span style="color: #002200;">&#123;</span>
<span style="color: #11740a; font-style: italic;">//[clone setLanguage:[self language]]; // 不再需要，父类实现了NSCopyObject()</span>
    Coder<span style="color: #002200;">*</span> clone <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super copyWithZone<span style="color: #002200;">:</span>zone<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>clone<span style="color: #002200;">-&amp;</span>gt;computer retain<span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// 父类实现了NSCopyObject()，虽然指针是拷贝过来了，但需要增加引用计数</span>
    <span style="color: #002200;">&#91;</span>clone setLeader<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self leader<span style="color: #002200;">&#93;</span> copyWithZone<span style="color: #002200;">:</span>zone<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;  <span style="color: #11740a; font-style: italic;">// 需要也进行copy的对象必须要调用copy，不管是不是NSCopyObject()</span>
    <span style="color: #a61390;">return</span> clone;
       <span style="color: #002200;">&#125;</span></pre></div></div>

<h3>dummy cloning和mutable copying</h3>
<p>简单来说就是返回一个自身引用</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> copyWithZone<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSZone</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>zone
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// 返回自身，增加一个引用</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self retain<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>作用？对于Mutable对象来说可以实现对于非Mutable对象的dummy clong后增加实现可变特性的方法。例如NSMutableString对于NSString</p>
<p>除了刚才的NSCopy外，还有一个NSMutableCopying协议，需要实现一个方法，它返回可变对象。操作方法是[object mutableCopy]。它的用处就是可以让Mutable Object的copy也是Mutable的，例如NSMutableArray如果用copy的话，返回的对象是不能修改的，这个时候需要用mutableCopy。具体的实现方法和copyWithZone没什么区别。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> mutableCopyWithZone<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSZone</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>zone;</pre></div></div>

<h2 id="chap02">02动态特性和RTTI</h2>
<h3>KVC（Key-Value Coding）</h3>
<p>可以通过字符串访问类成员。有点像字典。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>coder1 valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;leader&quot;</span><span style="color: #002200;">&#93;</span> GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>coder1 setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;New Si Wei&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span>coder1 GetInfo<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> TheSecondArg<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>对于成员的成员，需要用valueForKeyPath。当然对于自己的成员也可以用。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#91;</span>coder1 valueForKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;leader.name&quot;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>调用的顺序大概是</p>
<ul>
<li>valueForKey:@”foo”
<ol>
<li>getFoo方法、foo方法、isFoo方法</li>
<li>如果类accessInstanceVariablesDirectly返回YES那么是依次是_foo、_isFoo、foo和isFoo</li>
<li>还没找到就调用类的valueForUndefinedKey，默认行为是抛出异常NSUnknownKeyException</li>
</ol>
</li>
<li>setValue:forKey:@”foo”
<ol>
<li>setFoo方法</li>
<li>如果类accessInstanceVariablesDirectly返回YES那么是依次是_foo、_isFoo、foo和isFoo</li>
<li>还没找到就调用类的setValue:forUndefinedKey，默认行为是抛出异常NSUnknownKeyException</li>
</ol>
</li>
</ul>
<h3>introspection</h3>
<p>OOP语言必备的特性，简单说就是在运行时检查类的类型</p>
<p>从下面代码可以看出来，isKindOfClass检查对象是否是某类以及其子类的实例；isMemberOfClass只检查是否是某类的实例。</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">Class</span> personClass <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person class<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">Class</span> coderClass <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Coder class<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d, %d, %d, %d, %d, %d, %d, %d&quot;</span>,
        <span style="color: #002200;">&#91;</span>leader isMemberOfClass<span style="color: #002200;">:</span>personClass<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>leader isKindOfClass<span style="color: #002200;">:</span>personClass<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>leader isMemberOfClass<span style="color: #002200;">:</span>coderClass<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>leader isKindOfClass<span style="color: #002200;">:</span>coderClass<span style="color: #002200;">&#93;</span>,
        <span style="color: #002200;">&#91;</span>coder1 isMemberOfClass<span style="color: #002200;">:</span>personClass<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>coder1 isKindOfClass<span style="color: #002200;">:</span>personClass<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>coder1 isMemberOfClass<span style="color: #002200;">:</span>coderClass<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>coder1 isKindOfClass<span style="color: #002200;">:</span>coderClass<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
<span style="color: #11740a; font-style: italic;">//  YES, YES, NO, NO, NO, YES, YES, YES</span></pre></div></div>

<h3>实际编程中的一些动态特性类</h3>
<ul>
<li>SEL：selector相当于指向成员函数的指针，需要指定target才可以调用。通过selector生成的method signature可以用来初始化NSInvocation。
<ul>
<li>直接从方法名取得selector用@selector()或者NSSelectorFromString，逆操作NSStringFromSelector</li>
<li>对于实例用performSelector调用具体的方法</li>
</ul>
</li>
<li>Class：类的元数据，通过[instance class]、[instance className]或者NSClassFromString拿到，也有一个逆操作NSStringFromClass</li>
<li>IMP：其实就是一个函数指针，返回id，参数为id, selector, …，写着比自定义的方便而已，见下面的例子：</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">Person<span style="color: #002200;">*</span> me <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Person alloc<span style="color: #002200;">&#93;</span> initWithArgs<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;SW&quot;</span> TheAge<span style="color: #002200;">:</span><span style="color: #2400d9;">25</span><span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">SEL</span> selector <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>GetInfo<span style="color: #002200;">:</span>TheSecondArg<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>;
<span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">*</span>pFunc <span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span> <span style="color: #a61390;">id</span>, <span style="color: #a61390;">SEL</span>, <span style="color: #a61390;">int</span>, <span style="color: #a61390;">BOOL</span> <span style="color: #002200;">&#41;</span>;
pFunc <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span>, <span style="color: #a61390;">SEL</span>, <span style="color: #a61390;">int</span>, <span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>me methodForSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">IMP</span> imp <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>me methodForSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span>;
NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, pFunc<span style="color: #002200;">&#40;</span> me, selector, <span style="color: #2400d9;">100</span>, <span style="color: #a61390;">YES</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span>;
NSLog<span style="color: #002200;">&#40;</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span>imp<span style="color: #002200;">&#40;</span> me, selector, <span style="color: #2400d9;">100</span>, <span style="color: #a61390;">YES</span> <span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span>;</pre></div></div>

<ul>
<li>Invocation Forward：proxy类的工作，需要重载三个函数</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>respondsToSelector<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>aSelector：判断selector是否属于自己的某个成员
<span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMethodSignature</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>methodSignatureForSelector<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>aSelector：通过selector拿到method signature
<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>forwardInvocation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSInvocation</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>invocation：转发Invocation到相应的成员上
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMethodSignature</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> methodSignatureForSelector<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>selector <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMethodSignature</span><span style="color: #002200;">*</span> methodSig <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>fwdTarget methodSignatureForSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> methodSig <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> methodSig;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> forwardInvocation<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSInvocation</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> invocation <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>invocation invokeWithTarget<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self fwdTarget<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<h2 id="chap03">03内存管理和标准C区别</h2>
<h3>数据成员访问器</h3>
<p>数据成员的setter设定。不管哪个教程，都告诉我们setter是不能这么写的：</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> setLanguage <span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> aLanguage <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self language<span style="color: #002200;">:</span> aLanguage<span style="color: #002200;">&#93;</span>;  <span style="color: #11740a; font-style: italic;">// 糟糕代码！外部如果释放了aLanguage指向的对象，内部使用就会出错</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>也不能这么写</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">language <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>aLanguage retain<span style="color: #002200;">&#93;</span>;  <span style="color: #11740a; font-style: italic;">// 糟糕代码！内部成员原先指向的对象没法释放了！</span></pre></div></div>

<p>当然这样也不行</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>language release<span style="color: #002200;">&#93;</span>;
       <span style="color: #002200;">&#91;</span>self setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// 糟糕代码！如果language == aLanguage的话就多release了一次。</span></pre></div></div>

<p>所以我们被告知应该这么写</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>language autorelease<span style="color: #002200;">&#93;</span>;
       <span style="color: #002200;">&#91;</span>self setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// Good</span></pre></div></div>

<p>其实从第三个例子考虑，也可以写成</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>aLanguage retain<span style="color: #002200;">&#93;</span>;
       <span style="color: #002200;">&#91;</span>language release<span style="color: #002200;">&#93;</span>;
       <span style="color: #002200;">&#91;</span>self setLanguage<span style="color: #002200;">:</span>aLanguage<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>数据成员的getter设定。有的时候对于开放给外界的数据成员不希望进行修改，又不想用const关键字的话，可以考虑返回一个copy</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>Person<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> leader <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>leader copy<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">//return leader;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>当然能这么做的前提是Person类实现了copyWithZone</p>
<h3>release和垃圾收集器</h3>
<p>什么情况才需要autorelease？显式地调用了alloc、使用了copy（mutableCopy）以及retain之后。</p>
<p>垃圾收集器实现了一个灵活的GC，省得我们自己去retain, release和autorelease。开启了GC之后这三个函数都没用了。不过iPhone开发环境中似乎不能用GC？</p>
<p>__weak和__strong声明。什么时候需要弱引用？集合类，因为如果集合对其中的元素都拥有强引用的话，那么这些引用的实际对象就没法析构了（在集合类被咔嚓之前永远有一个ref count）。而弱引用在对象消失后自动变为nil。</p>
<p>autorelease不能滥用，因为它实际上是lazy deallocation，一般来说thread不结束都没法回收。</p>
<p>对于对象引用的维护，永远是使用者责任更大。因为开发者不知道自己的对象可能被引用多少次。</p>
<h3>这些东西不能用</h3>
<ul>
<li>模板</li>
<li>默认参数</li>
<li>Friend</li>
<li>inline（但其实Obj-C兼容C99，也可以使用inline关键字）</li>
<li>initialization list</li>
<li>方法的const修饰</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>阅读总结2011</title>
		<link>http://wei.si/blog/2011/12/reading-summary-2011/</link>
		<comments>http://wei.si/blog/2011/12/reading-summary-2011/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 16:37:43 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643564</guid>
		<description><![CDATA[终于到了2011最后一天，可以发各种总结了。阅读还是用http://imnerd.org/douban/进行统计。
题外话：动画和游戏
至于动画、游戏什么的，自然用Bangumi的年鉴功能。懒得单发，记录在此了：
「Bangumi 2011 年鉴」 2011 年，我看了 28 部动画，读了 本书，听了 1 张音乐，玩了 7 部游戏，看了 1 部剧集，参与了 73 次讨论，进行了 0 次条目编辑。
在这28部动画中印象最深刻的是还在放送的《ちはやふる》（歌牌情缘），游戏里面觉得最好的是一款老游戏《枪声与钻石》。当然今年玩游戏太少了，而且基本都是PSP上的AVG，最近这三个月已经写了大概四篇相关的玩后体会。
数据
回到正题，2011年的阅读数量为112，较之前年回落较多。原因不外乎是工作太忙，另外则是去掉了漫画，轻小说也只保留第一卷，确保统计水分不太大。

尽管如此，其实这112本书中有80%还是推理小说/轻小说，专业书以及学习类书籍大概只有10本……？所以推荐列表还是从推理小说开始吧（书籍链接在图片上）。
推荐的推理小说/轻小说类作品
     


东野圭吾《新参者》：带有主线的短篇集，东野今年在华语地区出版的最好的一本。本来对加贺刑警系列（为什么要专门写成刑警系列……一定不是《便当》的影响）并不感兴趣，但此本改变了我的想法。
虚渊玄《Fate/Zero》：爱的战士真的有两把刷子，比起Fate/Zero来说，Fate Stay/Night就是青春偶像剧了。
若竹七海《我的日常推理》：被喜欢/厌恶两个极端明显的一部推理作品，有人认为诡计是故弄玄虚，有人觉得喔喔喔这个安排简直超神了。我最喜欢里面利用虚拟的“公司杂志”目录作为章节分隔的做法。
小酒井不木《恋爱曲线》：日本侵华战前的推理集子，其时髦程度放在现在也很高，整本读下来非常痛快。
奈須きのこ《空之境界》：先看的动画剧场版，文字的力度甚至强于直观的画面表现。
逢坂刚《百舌呐喊的夜晚》：够冷够硬但又好读，简体也要买本！



其他类别的书籍推荐
      

禄是遒《中国民间迷信（崇拜）》系列：徐家汇藏书楼的良心作，虽然每本都是薄薄200-300页卖到40块，但总体来说是一套很有趣的风俗讲解和记录丛书。
艾伯特《神奇的二维国》：小说形式的科普读物，要考虑到这是1884年的作品，那只有用“神作”才能形容。希望大家都读读，为适应二向箔打击带来的新世界做好准备。另外推荐给妄图二次元去把虚拟妹子的2D厨。
杨显惠《夹边沟记事》：神作。
王爽《汇编语言》：从未见过一本语言类教程能写得如此让人看完一章还想看下一章。在遇到此书之前数次学习汇编都是半懂。用了半个月的业余时间看完后顺利入门。
比目鱼《虚拟书评》：之前在比目鱼Blog上看到这种形式的文章，太好玩了。见到此书变为实体还以为也是虚拟的……
王新禧译本《徒然草·方丈记》：王老师文笔真是巨好——除巨好以外我词穷找不出其他可形容的了——古风浓郁但又读起来不晦涩 （当然是对于我这种古文门外汉来说） ，实是译文典范。
Jeffrey Richter《CLR via C#》：夯实基础的必备知识，对于.net程序员来说不是只知道string有多少方法就行了。

雷区
既然有推荐肯定也有扫雷：

内田康夫《贵宾室的怪客》
东野圭吾《以眨眼干杯》。骗版税代表作。看完《新参者》再看这部，都会以为“东野圭吾”是个拥有数名文风迥异水平有天地之差的作家的写作团体。
麦家《风语》系列。作为麦家的死忠读者，我都以为买到盗名之作了。
二阶堂雷人老师的一切作品，以《双面兽事件》为代表。

]]></description>
			<content:encoded><![CDATA[<p>终于到了2011最后一天，可以发各种总结了。阅读还是用<a href="http://imnerd.org/douban/" target="_blank">http://imnerd.org/douban/</a>进行统计。</p>
<h2>题外话：动画和游戏</h2>
<p>至于动画、游戏什么的，自然用<a href="http://bgm.tv/award/2011" target="_blank">Bangumi的年鉴功能</a>。懒得单发，记录在此了：</p>
<blockquote><p>「Bangumi 2011 年鉴」 2011 年，我看了 28 部动画，读了 本书，听了 1 张音乐，玩了 7 部游戏，看了 1 部剧集，参与了 73 次讨论，进行了 0 次条目编辑。</p></blockquote>
<p>在这28部动画中印象最深刻的是还在放送的<a href="http://wei.si/blog/2011/11/chihayafuru/" target="_blank">《ちはやふる》（歌牌情缘）</a>，游戏里面觉得最好的是一款老游戏<a href="http://wei.si/blog/2011/09/jyuusei-to-diamond-played/" target="_blank">《枪声与钻石》</a>。当然今年玩游戏太少了，而且基本都是PSP上的AVG，最近这三个月已经写了大概四篇相关的玩后体会。</p>
<h2>数据</h2>
<p>回到正题，2011年的阅读数量为112，较之前年回落较多。原因不外乎是工作太忙，另外则是去掉了漫画，轻小说也只保留第一卷，确保统计水分不太大。</p>
<p><a href="http://wei.si/blog/wp-content/uploads/2011/12/read_2011.png"><img class="aligncenter size-medium wp-image-643565" title="read_2011" src="http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/read_2011-300x150.png" alt="" width="300" height="150" /></a></p>
<p>尽管如此，其实这112本书中有80%还是推理小说/轻小说，专业书以及学习类书籍大概只有10本……？所以推荐列表还是从推理小说开始吧（书籍链接在图片上）。</p>
<h2>推荐的推理小说/轻小说类作品</h2>
<p><a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="我的日常推理" href="http://book.douban.com/subject/6006584/" target="_blank"><img src="http://img3.douban.com/spic/s4657354.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="恋爱曲线" href="http://book.douban.com/subject/5349518/" target="_blank"><img src="http://img3.douban.com/spic/s4525343.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="空之境界（上下集合售）" href="http://book.douban.com/subject/1349295/" target="_blank"><img src="http://img3.douban.com/spic/s3018266.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="百舌吶喊的夜晚" href="http://book.douban.com/subject/1862497/" target="_blank"><img src="http://img3.douban.com/spic/s6801526.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="新參者" href="http://book.douban.com/subject/6535522/" target="_blank"><img src="http://img3.douban.com/spic/s6643996.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="Fate/Zero Vol.1 [第四次圣杯战争秘话]" href="http://book.douban.com/subject/3908784/" target="_blank"><img src="http://img1.douban.com/spic/s4499191.jpg" border="0" alt="" /></a></p>
<div id="_mcePaste">
<ul>
<li><strong>东野圭吾《新参者》</strong>：带有主线的短篇集，东野今年在华语地区出版的最好的一本。本来对加贺刑警系列（为什么要专门写成刑警系列……一定不是《便当》的影响）并不感兴趣，但此本改变了我的想法。</li>
<li><strong>虚渊玄《Fate/Zero》</strong>：爱的战士真的有两把刷子，比起Fate/Zero来说，Fate Stay/Night就是青春偶像剧了。</li>
<li><strong>若竹七海《我的日常推理》</strong>：被喜欢/厌恶两个极端明显的一部推理作品，有人认为诡计是故弄玄虚，有人觉得喔喔喔这个安排简直超神了。我最喜欢里面利用虚拟的“公司杂志”目录作为章节分隔的做法。</li>
<li><strong>小酒井不木《恋爱曲线》</strong>：日本侵华战前的推理集子，其时髦程度放在现在也很高，整本读下来非常痛快。</li>
<li><strong>奈須きのこ《空之境界》</strong>：先看的动画剧场版，文字的力度甚至强于直观的画面表现。</li>
<li><strong>逢坂刚《百舌呐喊的夜晚》</strong>：够冷够硬但又好读，简体也要买本！</li>
<li></li>
</ul>
</div>
<h2>其他类别的书籍推荐</h2>
<p><a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="中国民间崇拜" href="http://book.douban.com/subject/3702365/" target="_blank"><img src="http://img3.douban.com/spic/s4139177.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="神奇的二维国" href="http://book.douban.com/subject/3530171/" target="_blank"><img src="http://img3.douban.com/spic/s3699638.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="汇编语言" href="http://book.douban.com/subject/1215178/" target="_blank"><img src="http://img1.douban.com/spic/s4448052.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="夹边沟记事" href="http://book.douban.com/subject/3239549/" target="_blank"><img src="http://img1.douban.com/spic/s3294692.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="虚拟书评" href="http://book.douban.com/subject/4915930/" target="_blank"><img src="http://img3.douban.com/spic/s4418003.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="徒然草·方丈记" href="http://book.douban.com/subject/6877560/" target="_blank"><img src="http://img3.douban.com/spic/s6962253.jpg" border="0" alt="" /></a> <a style="float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;" title="CLR via C#" href="http://book.douban.com/subject/4112979/" target="_blank"><img src="http://img3.douban.com/spic/s4254428.jpg" border="0" alt="" /></a></p>
<ul>
<li><strong>禄是遒《中国民间迷信（崇拜）》系列</strong>：徐家汇藏书楼的良心作，虽然每本都是薄薄200-300页卖到40块，但总体来说是一套很有趣的风俗讲解和记录丛书。</li>
<li><strong>艾伯特《神奇的二维国》</strong>：小说形式的科普读物，要考虑到这是1884年的作品，那只有用“神作”才能形容。希望大家都读读，为适应二向箔打击带来的新世界做好准备。另外推荐给妄图二次元去把虚拟妹子的2D厨。</li>
<li><strong>杨显惠《夹边沟记事》</strong>：神作。</li>
<li><strong>王爽《汇编语言》</strong>：从未见过一本语言类教程能写得如此让人看完一章还想看下一章。在遇到此书之前数次学习汇编都是半懂。用了半个月的业余时间看完后顺利入门。</li>
<li><strong>比目鱼《虚拟书评》</strong>：之前在比目鱼Blog上看到这种形式的文章，太好玩了。见到此书变为实体还以为也是虚拟的……</li>
<li><strong>王新禧译本《徒然草·方丈记》</strong>：王老师文笔真是巨好——除巨好以外我词穷找不出其他可形容的了——古风浓郁但又读起来不晦涩 （当然是对于我这种古文门外汉来说） ，实是译文典范。</li>
<li><strong>Jeffrey Richter《CLR via C#》</strong>：夯实基础的必备知识，对于.net程序员来说不是只知道string有多少方法就行了。</li>
</ul>
<h2>雷区</h2>
<p>既然有推荐肯定也有扫雷：</p>
<ul>
<li>内田康夫《贵宾室的怪客》</li>
<li>东野圭吾《以眨眼干杯》。骗版税代表作。看完《新参者》再看这部，都会以为“东野圭吾”是个拥有数名文风迥异水平有天地之差的作家的写作团体。</li>
<li>麦家《风语》系列。作为麦家的死忠读者，我都以为买到盗名之作了。</li>
<li>二阶堂雷人老师的一切作品，以《双面兽事件》为代表。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2011/12/reading-summary-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《深度探索C++对象模型》学习笔记（5-7章）</title>
		<link>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/</link>
		<comments>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 14:13:23 +0000</pubDate>
		<dc:creator>Si Wei</dc:creator>
				<category><![CDATA[未分类]]></category>
		<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://wei.si/blog/?p=643514</guid>
		<description><![CDATA[第5章 构造析构和拷贝
虚函数
对于抽象类而言，是否应该自己负责初始化类内的数据成员？（别忘了抽象类也可以有非纯虚函数和数据成员）

一般情况下被认为子类要负责从基类继承来的数据成员的初始化
或者基类必须提供一个显式的构造函数用于自己数据成员的初始化
最好的方法则是将行为和数据分离，提供接口专门用于定义方法


class A_B
&#123;
public:
    virtual ~A_B&#40;&#41; = 0;
    virtual void Say&#40;&#41; const = 0;
    inline char const* GetData&#40;&#41; const &#123; return iData; &#125;
protected:
    A_B&#40; char* aData &#41; : iData&#40; aData &#41; &#123;  &#125;
protected:
    char* iData;
&#125;;
inline A_B::~A_B&#40;&#41; &#123;&#125;
&#160;
class C_D : public [...]]]></description>
			<content:encoded><![CDATA[<h2>第5章 构造析构和拷贝</h2>
<h3>虚函数</h3>
<p>对于抽象类而言，是否应该自己负责初始化类内的数据成员？（别忘了抽象类也可以有非纯虚函数和数据成员）</p>
<ul>
<li>一般情况下被认为子类要负责从基类继承来的数据成员的初始化</li>
<li>或者基类必须提供一个显式的构造函数用于自己数据成员的初始化</li>
<li>最好的方法则是将行为和数据分离，提供接口专门用于定义方法</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> A_B
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">virtual</span> ~A_B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Say<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">char</span> <span style="color: #0000ff;">const</span><span style="color: #000040;">*</span> GetData<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> iData<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    A_B<span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> aData <span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> iData<span style="color: #008000;">&#40;</span> aData <span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>  <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> iData<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">inline</span> A_B<span style="color: #008080;">::</span>~A_B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">class</span> C_D <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> A_B <span style="color: #666666;">// concrete derived class</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    C_D<span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> aData, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> aData2 <span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span>
           A_B<span style="color: #008000;">&#40;</span> aData <span style="color: #008000;">&#41;</span>, iData2<span style="color: #008000;">&#40;</span> aData2 <span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;c_d ctor&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~C_D<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">delete</span> iData2<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Say<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;c_d says: &quot;</span><span style="color: #000080;">&lt;&lt;</span>iData<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">void</span> Say2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;c_d says2: &quot;</span><span style="color: #000080;">&lt;&lt;</span>iData2<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> iData2<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>纯虚函数</p>
<ul>
<li>拥有定义的纯虚函数（这还叫纯虚函数么）可以在子类中进行调用。不过就是什么用都没有罢了。</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">//定义</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">void</span> A_B<span style="color: #008080;">::</span><span style="color: #007788;">Say</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;hey!&quot;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #666666;">//调用，发现hey!并没有打印出来</span>
<span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Say<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> A_B<span style="color: #008080;">::</span><span style="color: #007788;">Say</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;c_d says: &quot;</span><span style="color: #000080;">&lt;&lt;</span>iData<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span></pre></div></div>

<ul>
<li>实际上是否让纯虚函数拥有（没用的）定义由程序员说了算。</li>
<li>但唯一的例外是纯虚析构函数，必须像上面那样进行显式定义 A_B::~A_B() {}
<ul>
<li>否则就会出现错误，严格来说并非编译错误，而是链接错误。</li>
<li>原因很简单，析构函数和构造函数一样，子类的都会由编译器进行扩充，调用基类的版本。</li>
<li>不希望这么定义的话，解决方法只有生命非纯虚的析构函数</li>
</ul>
</li>
</ul>
<p>Virtual Specification</p>
<ul>
<li>不加选择地将函数设定为virtual在效率上会不升反降，不能依赖编译器的优化</li>
<li>应付const也会令人头疼，例如在基类中不需要修改的const ref或者const pointer，到了子类就需要修改了。目前最好的方法是不用const（……无语）</li>
<li>需要考虑到的（不全）
<ul>
<li>抽象类的构造函数需要负责初始化自己的数据成员，可以声明为protected避免外部访问</li>
<li>缺少多态需求的函数不要设定为virtual，尤其是inline函数</li>
<li>慎用const，除非确定派生类也不会修改const修饰的对象</li>
</ul>
</li>
</ul>
<h3><span id="more-643514"></span></h3>
<h3>对象构造</h3>
<p>无继承情况下的对象构造（限于一个class内都是public访问级别的对象）</p>
<ul>
<li>class B { public: int a, b, c; }</li>
<li>C中的全局变量会被视为“临时性的定义”而只保留一个实体，位于DS的末端，称为BSS（Block Started by Symbol）的区域</li>
<li>对于new和delete运算符的操作，不会触发trivial构造函数和析构函数</li>
<li>而传值方式的return操作，感觉上会触发trivial copy constructor，但实际上只是位拷贝</li>
<li>显式地设定类对象的数据成员值如何？例如B b; b.a = 1; b.b = &#8230;
<ul>
<li>效率不如初始化列表高</li>
<li>而且所设定的成员访问范围只能是public</li>
<li>但也不是一无是处。对于大数据量、常量赋值的情况，显示设定数据的方式反而效率更高一点</li>
</ul>
</li>
</ul>
<p>多了private接口和inline的构造函数，但无virtual特性</p>
<ul>
<li>class B { public: B ( int aA = 0, int aB = 0, int aC = 0 ) : a(aA), b(aB), c(aC) {} private: int a, b, c; }</li>
<li>大小不会变化，默认的构造函数、析构函数和拷贝构造也够用了。提供初始化列表会比较高效</li>
<li>编译器会进行优化，将inline的构造函数在对象声明处（不是构造函数内！）展开为显示设定成员的方式，利用常量赋值</li>
<li>new运算符则会有些变化 B* b = __operator_new( sizeof (B) ); if ( b != NULL ) then b->B::B(); 多了一个指针大小非零的判断</li>
<li>而其他的，例如delete运算符、传值返回等，和上面的一样</li>
</ul>
<p>多了virtual函数的引入</p>
<ul>
<li>class B { public: B ( int aA = 0, int aB = 0 ) : a(aA), b(aB) {} virtual int C(); private: int a, b, c; }</li>
<li>最先想到的：每一个B对象都会有一个vptr指向vtbl，这个vptr占用一个字长。这种额外消耗是否值得要看多态所带来的价值是否大于vptr所带来的空间消耗</li>
<li>其他的代价
<ul>
<li>构造函数会自动被添加代码，用于初始化vptr。这些代码位于所有的基类构造函数之后、程序员的代码之前。（展开后）类似于</li>
</ul>
</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">B<span style="color: #000040;">*</span> B<span style="color: #008080;">::</span><span style="color: #007788;">B</span><span style="color: #008000;">&#40;</span> B<span style="color: #000040;">*</span> <span style="color: #0000dd;">this</span>, <span style="color: #0000ff;">int</span> aA, <span style="color: #0000ff;">int</span> aB <span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>__vptr_point <span style="color: #000080;">=</span> __vtbl_point<span style="color: #008080;">;</span>
this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>a <span style="color: #000080;">=</span> aA<span style="color: #008080;">;</span>
this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>b <span style="color: #000080;">=</span> aB<span style="color: #008080;">;</span>
<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<ul>
<li>不再为trivial的拷贝构造函数和拷贝运算符函数（但隐式的析构函数仍然是trivial的）
<ul>
<li>类似于构造函数，需要拷贝vptr以及相关的数据成员（参看“构造函数：拷贝构造函数”），有可能是非bitwisely copy。这也是需要编译器合成不再trivial的拷贝函数（运算符）的原因之一。</li>
</ul>
</li>
<li>另外一个原因则是返回值的需要。作为引用参数之一的返回值需要拷贝构造函数获得vptr，同时销毁局部变量。</li>
<li>由此引出的想法：有关显式拷贝构造函数的必要性——大量传值返回某类的情况下。</li>
</ul>
<p><a name=".E6.9C.89.E7.BB.A7.E6.89.BF.E5.AF.B9.E8.B1.A1.E6.9E.84.E9.80.A0"></a></p>
<h3>有继承对象构造</h3>
<p>回顾：构造函数的工作</p>
<ul>
<li>如果有的话，调用所有虚基类构造函数</li>
<li>如果有基类的话，调用基类的构造器。如果有多个基类，调用顺序为声明的顺序
<ul>
<li>位于构造列表里面的，直接以参数进行调用</li>
<li>并非位于列表里面的，调用默认的构造函数</li>
<li>如果是多重继承的基类，那么需要进行this指针的调整</li>
</ul>
</li>
<li>初始化vptr指向相应的vtbl</li>
<li>函数初始化列表会被编译器展开放置于构造函数之中（参见2.3）</li>
<li>没有位于列表中的数据成员，如果拥有默认构造器，那么需要进行调用</li>
</ul>
<p>拷贝构造函数中“自我拷贝”检查的必要性</p>
<ul>
<li>并非大问题，但在B b1; b2 = b1; b1 = b2;情况下，如果没有进行this指针的检查，类似的操作会导致额外的开销</li>
<li>目前的编译器都不会对此进行检查，需要程序员进行自律</li>
</ul>
<p>有继承情况下的对象构造，虚拟继承</p>
<ul>
<li>回顾：虚拟继承需要添加虚基类子对象（virtual base class subobject），几种解决方式（参见3.3）</li>
<li>在虚拟继承中单纯地对每一个构造函数进行扩充是不可行的。
<ul>
<li>需要增加一个是否为最底层对象的检查，如果是才负责初始化从最上层基类所继承下来的数据成员。</li>
</ul>
</li>
</ul>
<p>vptr初始化</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Base <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;base::info&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">int</span> iBaseValue<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Derive1 <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> Base <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;derived1::info&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">int</span> iDerive1Value<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Derive2 <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> Base <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;derived2::info&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">int</span> iDerive2Value<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> DD <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Derive1, <span style="color: #0000ff;">public</span> Derive2 <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;dd::info&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">int</span> iDDValue<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> DDD <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> DD <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;ddd::info&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span> <span style="color: #0000ff;">int</span> iDDDValue<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<ul>
<li>基类指针指向的子类对象，调用的函数实体为子类对象的</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">   DDD ddd<span style="color: #008080;">;</span>
   Derive1 d1<span style="color: #008080;">;</span>
   Base<span style="color: #000040;">*</span> b <span style="color: #000080;">=</span> <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>ddd<span style="color: #008080;">;</span>
   b<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//&quot;ddd::info&quot;</span>
   b <span style="color: #000080;">=</span> <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>d1<span style="color: #008080;">;</span>
   b<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Info<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//&quot;derived1::info&quot;</span></pre></div></div>

<ul>
<li>如果在构造函数中调用成员函数会如何？构造一个子类对象时候，每次的构造函数会被认为是调用最底层子类的还是当前类本身的？
<ul>
<li>当然是类本身的！因为构造的时候是按照从上到下的顺序。derive1构造的时候，ddd还尚未在内存中出现，更不要提它继承出来的Info函数了</li>
<li>同时这也是构造函数不可为虚函数的一个原因（抽象工厂除外）</li>
</ul>
</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">base<span style="color: #008080;">::</span><span style="color: #007788;">info</span>
derived1<span style="color: #008080;">::</span><span style="color: #007788;">info</span>
derived2<span style="color: #008080;">::</span><span style="color: #007788;">info</span>
dd<span style="color: #008080;">::</span><span style="color: #007788;">info</span>
ddd<span style="color: #008080;">::</span><span style="color: #007788;">info</span></pre></div></div>

<ul>
<li>再考虑一种情况，如果Info()又调用了一个虚函数，例如VF()会如何？按照上面第二条的说法，运行时应该调用的是子类的函数。但构造时候很明显会调用基类的
<ul>
<li>实验的结果是，构造函数时候调用了各个基类自己的VF()，而运行的时候不出所料，就算用Base*指向了子类对象，调用的也是ddd::VF()。</li>
<li>编译器的做法是对于在构造函数中的虚函数调用进行特殊处理，声明为静态方式的调用，不要用虚拟特性解决</li>
<li>说起来简单，但实际上编译器所做的工作要复杂得多，首先要通过vptr拿到vtbl，获取虚函数的列表，这些函数都是在构造函数调用中不能表现出虚拟特性的</li>
<li>由此而衍生出的问题是vptr的初始化时间。显然要早于任何程序员写在构造函数中的代码，但要晚于vtbl和基类构造函数的创建</li>
<li>通过这么多学习，再次回顾构造函数步骤时候会觉得比之前要清晰很多，显然我们在构造一个基类的时候，首先要考虑虚拟继承的情况，判断自己是否为最底层的子类，如果是的话要负责构造基类；之后按照顺序构造所有基类；接下来根据基类的信息拿到vtbl中的虚函数列表；最后执行程序员自己写的代码</li>
</ul>
</li>
</ul>
<p>构造函数初始化列表中调用虚函数是否安全？</p>
<ul>
<li>形如 Derived( int aValue, int aValue2 ) : Base( F( aValue ) ), iValue ( aValue2 ) { } // F为虚函数</li>
<li>分情况讨论。如果不需要对基类在初始化列表中同样进行初始化，那么应该是安全的。考虑一下，vptr在此时应该已经设置完毕，展开初始化列表的时候，虚函数可以正确地通过指针拿到。当然有一点需要注意的是被调用的虚函数可能会使用没有初始化的数据成员，但这不是我们讨论的问题了。所以结论是，OK，没问题，只是不推荐这么做而已。</li>
<li>如果需要在初始化列表中对基类进行初始化，那么是绝对不安全的！基类的构造要早于子类的函数被创建，但在初始化列表展开之前，基类构造的时候就要使用子类虚函数的话，很显然是行不通的：有可能指向定义这个函数的vtbl的vptr尚未创建成功，或者可能指向了错误的类对象。（不过在gcc上貌似没有什么问题）</li>
</ul>
<p><a name=".E6.8B.B7.E8.B4.9D.E5.92.8C.E8.B5.8B.E5.80.BC"></a></p>
<h3>拷贝和赋值</h3>
<p>依然先要回顾一下</p>
<ul>
<li>什么时候编译器会生成一个默认的拷贝构造函数？需要的时候，但并非所有情况（参见2.2）</li>
<li>是否需要自己写拷贝构造函数需要斟酌。对于bitwise copy足够的情况没有必要自己编写</li>
</ul>
<p>对于拷贝运算符来说以下情况是不会进行Bitwise copy的（同样参见2.2构造函数：拷贝构造函数）</p>
<ul>
<li>数据成员中有拥有拷贝运算符的类型</li>
<li>基类中有拷贝运算符</li>
<li>类中有虚函数（因为等号右边的对象可能是个子类）</li>
<li>继承自虚基类</li>
</ul>
<p>其实就是一句话……如果默认的bitwise copy（memberwise assignment）不能满足需要的时候，会出现默认的拷贝运算符 如果默认的也不能满足需要，那就得自己写一个拷贝运算符进行深拷贝 编译器在需要的时候会生成拷贝运算符</p>
<ul>
<li>生成出来的类似于：</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">inline</span> D<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> D<span style="color: #008080;">::</span><span style="color: #007788;">operator</span><span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span> D<span style="color: #000040;">*</span> <span style="color: #0000ff;">const</span> <span style="color: #0000dd;">this</span>, D<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> rhs <span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>B<span style="color: #008080;">::</span><span style="color: #007788;">operator</span><span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span> rhs <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
iValue <span style="color: #000080;">=</span> rhs.<span style="color: #007788;">Value</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<ul>
<li>可惜只能这么做，因为没有一个类似于构造函数一样的“拷贝初始化列表”</li>
<li>通过this指针取到基类运算符进行赋值也可以用这个代替： ( *(B*)this) ) = rhs;，这样转化成了通过基类指针对对象进行值拷贝</li>
<li>关键问题就在于怎么拿到基类的运算符重载函数，另外则是如果有多继承的情况，如何只（在最底层的子类）执行一次拷贝操作？
<ul>
<li>嗯……通过指向成员函数的指针：</li>
</ul>
</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> B<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> <span style="color: #008000;">&#40;</span>B<span style="color: #008080;">::</span><span style="color: #000040;">*</span>POF<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> B<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
POF pOF <span style="color: #000080;">=</span> <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>B<span style="color: #008080;">::</span><span style="color: #007788;">operator</span><span style="color: #000080;">=</span><span style="color: #008080;">;</span>
D.<span style="color: #000040;">*</span>pOF<span style="color: #008000;">&#40;</span> anotherD <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<ul>
<li>
<ul>
<li>其丑无比！</li>
</ul>
</li>
<li>其实很多编译器在虚继承的时候处理拷贝运算符比较苦手</li>
<li>所以最简单的方式就是执行多次拷贝，只要保证当前类的调用位于所有的基类之后就行——虽然这样一来虚基类子对象会复制多次</li>
</ul>
<p><a name=".E6.9E.90.E6.9E.84"></a></p>
<h3>析构</h3>
<p>同构造函数、拷贝函数的情况类似，析构函数只有在需要的时候（基类有析构函数、数据成员有析构函数）的情况下才被生成出来 顺序和构造函数正好相反</p>
<ul>
<li>析构函数执行程序员的代码</li>
<li>如果类的数据成员拥有析构函数，那么也会调用，不过顺序和声明相反</li>
<li>对象内有vptr的话，那么重设vtbl</li>
<li>如果基类拥有析构函数的话，同样相反调用</li>
<li>如果虚基类拥有析构函数的话，且当前类是最底层的子类，那么同样相反调用</li>
</ul>
<p>整个过程类似“脱壳”一样，从下至上地析构，子类逐渐地变为上层基类、上上层基类、上上上层……（如果有的话） 两种析构函数的版本</p>
<ul>
<li>完整的对象，设置vptrs，调用虚基类的析构函数</li>
<li>基类子对象，除非析构函数中调用了虚函数，否则不会设置vptrs、调用虚基类的析构函数</li>
</ul>
<p><a name=".E7.AC.AC6.E7.AB.A0_.E6.89.A7.E8.A1.8C.E6.9C.9F"></a></p>
<h2>第6章 执行期</h2>
<p><a name=".E6.9E.84.E9.80.A0.E5.92.8C.E6.9E.90.E6.9E.84"></a></p>
<h3>构造和析构</h3>
<p>局部对象的构造析构</p>
<ul>
<li>对于switch/case、goto等指令析构函数可能会被安排出现多次：每个函数的退出点都需要有一个</li>
<li>但位于局部对象声明之前的，不需要</li>
</ul>
<p>全局对象</p>
<ul>
<li>全局对象的生存期为main()之前构造而函数结束前析构</li>
<li>放置的位置为DS（5.2构析拷贝：对象构造）</li>
<li>为了支持类对象的静态初始化，需要在有虚继承的情况下进行指针调整，将子类中vbc pointer的正确位置返回</li>
</ul>
<p>局部对象</p>
<ul>
<li>局部静态对象声明一次，只会初始化和销毁一次。初始化的地点和全局对象一样，即时对象所在的函数并未被调用</li>
<li>闭包的概念。</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> foo2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>i<span style="color: #000040;">++</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
    foo2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 0</span>
    foo2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 1</span></pre></div></div>

<p>数组</p>
<ul>
<li>如果数组元素没有显式的构造函数和析构函数，那么分配足够的空间就够了</li>
<li>但如果有的话，参考cfront的解法，定义一个新的函数vec_new，参数分别为数组起始地址、类对象大小、数组元素个数、构造函数和析构函数的指针
<ul>
<li>与之对应的数组析构函数vec_del只接受一个析构函数指针就足够，然后针对所有元素遍历调用</li>
</ul>
</li>
<li>例如B bases[10];就会变为 vec_new( &amp;bases, sizeof( B ), 10, B::B, 0 );，函数会对于传入的所有对象分别调用其构造和析构函数
<ul>
<li>程序员提供了初始值的情况呢？例如 B bases[10] = { B(), B( 1 ), 2 };</li>
<li>编译器会解析出已经赋值的部分，将其变为构造函数的调用，再对剩余的对象调用vec_new，当然，数组起始地址和元素个数都会不同</li>
</ul>
</li>
<li>大概类似于B::B( &amp;bases[0], 0 ); B::B( &amp;bases[1], 1 ); B::B( &amp;bases[2], 2 ); vec_new( &amp;bases+3, sizeof( B ), 7, B::B, 0 );
<ul>
<li>cfront 2.0之前，数组无法应付超过一个默认参数的构造函数或者默认构造函数，回顾上面的vec_new函数，我们如何调用到拥有多个默认参数的构造函数指针？</li>
</ul>
</li>
</ul>
<p>cfront的编译器多加了一个stub的构造函数（同样也是没有参数），里面调用程序员写的带有多个默认参数的构造函数</p>
<p><a name="new.E5.92.8Cdelete"></a></p>
<h3>new和delete</h3>
<p>new运算符</p>
<ul>
<li>简单的一个new运算符语句其实包括多个步骤。例如int* pi = new int( 5 );
<ol>
<li>首先调用__new函数进行内存分配int* pi = __new ( sizeof(int ) );</li>
<li>赋值 *pi = 5。</li>
<li>实际上第一步中应该多判断一下pi是否不为0再赋值</li>
</ol>
</li>
<li>对于类对象来说。例如Base* pb = new Base( pb, 5 );
<ol>
<li>类似于上面的做法，分配内存先 Base* pb; pb = __new( sizeof( B ) );</li>
<li>赋值 *pb = Base::Base( 5 );</li>
<li>实际情况需要考虑的还要更多，例如在拷贝构造的时候，函数有可能抛出异常。如果catch到的话需要__delete掉已经分配的内存空间</li>
</ol>
</li>
</ul>
<p>delete运算符</p>
<ul>
<li>也是交给内置函数去做的。例如delete pi;
<ol>
<li>变为if ( pi != 0 ) __delete( pi );</li>
<li>不过由于不会重置内存，所以之后再判断pi是否为null甚至*p去取值都有可能成功。</li>
</ol>
</li>
<li>对于类对象的析构来说。例如delete pb;
<ol>
<li>变为if ( pb != 0 ) { Base::~Base( pb ); __delete( pb ); }</li>
</ol>
</li>
</ul>
<p>new和delete运算符的实现</p>
<ul>
<li>首先是size为0的情况会自动调整为1，这是因为每一次new出来的指针都应该是不同的，所以就算size为0，也要指向不同的1-byte内存区域。</li>
<li>声明void*指针，用malloc拿到相应size的空间并且返回指针</li>
<li>delete采用free()实现</li>
</ul>
<p>数组的new运算符</p>
<ul>
<li>例如int* pi = new int[5]; 或者MyStruct* ps = new MyStruct[5]; //MyStruct是结构体
<ul>
<li>内置类型时vec_new并不会调用，因为它作用就是遍历调用构造函数，但上面两种类型都没有</li>
<li>只有__new用来分配空间</li>
</ul>
</li>
<li>对于拥有默认构造器的类来说，数组初始化时候也需要析构函数指针，因为可能发生异常，以便清理已经分配的空间（6.1执行期：构造和析构第4节）</li>
<li>C++ 2.0之前在delete掉数组时候，需要程序员手动指定元素个数，例如delete [5] pi;
<ul>
<li>但之后就不用了，就像我们现在所使用的那样delete[] pi;</li>
<li>实现这个功能需要知道数组首地址和元素的个数。但这样做需要更多性能上的开销。所以如果没带[]调用delete，只会删掉一个元素</li>
<li>具体来说，即将vec_new返回的内存地址多加一个word长度的信息，保存数组长度（所谓cookie）</li>
<li>但Sun编译器的做法是维护一个保存数组指针和大小的额外数组，其中还放置析构函数的地址</li>
</ul>
</li>
<li>继承情况下的问题
<ul>
<li>D继承于B，都实现了虚析构函数。那么B* pb = new D[ 5 ];如何？</li>
<li>语法上OK，但delete [] pb时候问题来了……vec_del只会调用5次B类的析构函数，D的却没有。因为它总是执行被删除类型的析构函数。
<ul>
<li>vec_del只会调用5次B类的析构函数，D的却没有。因为它总是执行被删除类型的析构函数。</li>
<li>更可怕的是，由于传入的元素大小是sizeof( B )，显然在pb++的时候移动的距离并非预期的D的长度，也就是说析构函数指针所作用的内存区域必然会出现错误</li>
</ul>
</li>
<li>如果非得这么干的话，需要程序员自己解决问题：遍历数组每一个元素，然后 D* d = &amp;((D*)pb)[i]; delete d;</li>
</ul>
</li>
</ul>
<p>new运算符的重载</p>
<ul>
<li>例如B* b = new (arena) B();，这里的arena为指定的的内存区域</li>
<li>实际上编译器做的事情就是将传入的arena参数返回而已</li>
<li>在编译器其实就相当于B* p = (B*) arena; 不过要做的事情除了决定arena的类型，还得 p->B::B();</li>
<li>重复利用一块区域进行构造如何？例如上面操作后再 b = new (arena) B();
<ul>
<li>那么之前new出来的对象不会被析构。</li>
<li>直接delete b的话，是有问题的，虽然可以调用到析构函数，但b占用的内存区域同样也回收了</li>
<li>所以需要b->~b();</li>
<li>不过标准C++中不需要这么做，编译器的__delete();会进行析构但不释放内存区域</li>
</ul>
</li>
<li>C++标准里面规定，利用同一块内存构造新对象的时候，要么是同一类型，要么就是全新的区域，并且大小足够放下这个object</li>
<li>这么一来，继承的类就不好说了，所以这种new运算符的重载基本是不支持多态的</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">B b<span style="color: #008080;">;</span>
    b.<span style="color: #007788;">ToString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    b.~B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">new</span> <span style="color: #008000;">&#40;</span> <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>b <span style="color: #008000;">&#41;</span> D<span style="color: #008080;">;</span>
    b.<span style="color: #007788;">ToString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<ul>
<li>
<ul>
<li>哪个类的ToString被调用了？实际上是B的……</li>
</ul>
</li>
</ul>
<p><a name=".E4.B8.B4.E6.97.B6.E5.AF.B9.E8.B1.A1"></a></p>
<h3>临时对象</h3>
<p>不太严谨但清晰的定义是：没有别名的局部对象 T a, b; T c = a + b;</p>
<ul>
<li>不能肯定是否调用了c的拷贝构造函数，并且利用a+b产生的临时对象作为参数</li>
<li>因为可能产生的NRV优化以及不同的加号运算符重载，可能会直接将a+b的值放入c内</li>
</ul>
<p>对于T c = a + b; 和T c; c = a + b;来说可能导致完全不同的结果</p>
<ul>
<li>前者一般都会调用重载的等号运算符，直接传入局部对象引用作为第一个参数</li>
<li>而后者总是会产生临时对象，调用其等号运算符、再析构</li>
<li>另外后者需要保证“c是全新的”，而等号运算符又不会调用析构，所以必须保证在赋值前进行析构。</li>
<li>一般而言前者效率更好</li>
</ul>
<p>关键问题在于临时对象的生存期，即何时调用它的析构函数才合适</p>
<ul>
<li>C++标准规定：对于临时对象的析构应该是完整表达式求值的最后一个步骤</li>
<li>换句话说在表达式被完全求值之前，所有为此产生的临时对象都不能销毁</li>
<li>也有例外
<ul>
<li>利用表达式初始化对象 String s = flag ? null : s1 + s2;，也就是说在?后s1+s2产生的临时对象就要析构了。但如果String需要用拷贝构造函数进行初始化的话，必然会位于析构之后，所得到的值也会是错误的。</li>
<li>利用对象初始化引用时。如果String&amp; s = s1 + s2; 如果引用的临时对象析构了，那引用就没意义了。所以这种情况下，临时对象会在引用失效或者自身失效后进行析构，哪个先到算哪个。</li>
</ul>
</li>
</ul>
<p><a name=".E7.AC.AC7.E7.AB.A0_.E7.BB.88.E7.AB.A0"></a></p>
<h2>第7章 终章</h2>
<p><a name="Template"></a></p>
<h3>Template</h3>
<p>Template是个非常强大的语法，毋庸置疑。它提供了C++的泛型特性。但由于使用不便，很多人不愿意用。相较于更现代的语言，例如C#和Java，C++利用Template实现的泛型确实不太好理解。 Template的“绑定”会直接替换实际的类型到形参上 对于在Template类里面生命的各种成员而言，编译器在处理Template时候，它们还没有被生成。只有绑定了类型之后才可以使用。例如一个Class B拥有一个enum对象TStatus。但不能直接用B::Status，而只能B<int>::Status。</p>
<ul>
<li>所以对于常量之类的，尽量从Template类中提取出来，避免多次拷贝</li>
</ul>
<p>对于指针和引用的区别对待</p>
<ul>
<li>B<int>* b = 0;这样做不会产生一个B的实体出来，实际上现在C++标准也禁止编译器这么做</li>
<li>B<int>&amp; b = 0;这样则会产生一个实体。因为引用不能为空，展开后类似于B<int> tmp( int( 0 ) ); const B<int>&amp; b = tmp;</li>
</ul>
<p>Template的实例化（instantiation）</p>
<ul>
<li>指针和引用的例子参见上一条</li>
<li>并非一次性都实例化完成，用到的才实例化。例如B<int>* b = new B<int>(0); 只会实例化Template本身、构造、析构函数。这是出于效率的考虑。另外new运算符虽然是static的，但它也间接依赖于Template的参数：对象的大小。</li>
</ul>
<p>Template的错误处理</p>
<ul>
<li>一些潜在的错误（非语法错误）：例如给指针赋了错误的值（int* = 1024）、使用类没有实现的运算符。不过编译器都会在实例化Template时候判断出来</li>
</ul>
<p>名称问题</p>
<ul>
<li>Template类的定义范围内有一个extern函数，和使用处定义的一个extern函数重名了，那么在Template类成员函数中调用的到底是那个函数？</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">//template定义范围内</span>
<span style="color: #0000ff;">extern</span> <span style="color: #0000ff;">double</span> foo<span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">double</span> aValue <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> C1
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> _v1 <span style="color: #000080;">=</span> foo<span style="color: #008000;">&#40;</span> _v2 <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    bar2<span style="color: #008000;">&#40;</span> T aValue <span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> _v1 <span style="color: #000080;">=</span> foo<span style="color: #008000;">&#40;</span> aValue <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    T _v1<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> _v2<span style="color: #008080;">;</span>
<span style="color: #666666;">//template使用范围内</span>
<span style="color: #0000ff;">extern</span> <span style="color: #0000ff;">int</span> foo<span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">int</span> aValue <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
C1<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> c<span style="color: #008080;">;</span>
c.<span style="color: #007788;">bar</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<ul>
<li>上例中是定义范围内的那个，而不是适用范围内，符合参数类型的那个。</li>
<li>原则：调用的函数是否和使用的类型相关，不相关就直接使用定义范围的。本例中_v2是很明显的int，不会随着模板参数类型变化而变化，所以直接使用定义范围的。所以如果是调用了bar2()的话，那就会选择使用范围的那个foo()。</li>
</ul>
<p>成员函数</p>
<ul>
<li>编译器寻找函数定义：遵循一定的规则，例如一定在头文件对应的同名cpp文件内</li>
<li>寻找成员函数：Borland生成所有函数；cfront的方法是模拟链接（simulate linkage），只生成需要的</li>
<li>成员函数实体的唯一性：生成一份，然后在.o中链接</li>
</ul>
<p><a name=".E5.BC.82.E5.B8.B8.E5.A4.84.E7.90.86"></a></p>
<h3>异常处理</h3>
<p>中心思想：发生异常的时候查找catch，将局部变量析构掉后让当前函数unwind</p>
<ul>
<li>所以看起来很像的代码可能由于异常处理机制的存在而拥有差别很大的执行期语义</li>
</ul>
<p>对于类似互斥锁之类的操作，如果异常发生在lock之后，如何进行unlock？</p>
<ul>
<li>提供多个unlock操作，分别放在可能的路径上</li>
<li>对于更现代的语言来说，都拥有类似finally这样子句来支持异常发生后的对象清理操作</li>
</ul>
<p>再例如一个子类指针指向的数组，分配到某一个元素的基类区域时候发生了一场，那么之前的元素都需要分别调用子类和基类的析构，而发生错误的那个元素只要调用基类的即可，因为子类尚未构造出来。 代码会被划分为多个区段，因为在异常发生前的对象都需要调用析构进行清除，之后的则不用</p>
<ul>
<li>try以外的，没有局部对象的代码段、try以外的，有局部对象的代码段，try代码段</li>
<li>实现方法：program counter-rage table。记录各个代码段的起始/终止位置</li>
<li>发生异常的时候，如果当前位置位于try代码段之中，那么就寻找try字句处理</li>
</ul>
<p>异常发生的时候会产生异常对象（exception object），放置在异常栈中</p>
<ul>
<li>throw出去的是地址、type identifier以及可能的异常对象TI</li>
<li>如果跑出了异常子类而catch的是基类，exObj会被slice off掉非基类的部分</li>
<li>catch字句结束时，当前的局部exObj就会被销毁。所以如果再一次抛出异常的话，捕获的又是原来的对象了（这节翻译的也太烂了！）</li>
</ul>
<p><a name="RTTI"></a></p>
<h3>RTTI</h3>
<p>cfront2.0之前，转型运算符*是不能够被重载的</p>
<ul>
<li>不过之后就可以了</li>
</ul>
<p>downcast：有用、常用甚至是必要的——但不一定安全的操作 类型安全的downcast操作</p>
<ul>
<li>为了支持安全的downcast需要额外开销：类型信息（TI）和运行时的类型判断（runtime type）</li>
<li>所以TI的信息就放在vtbl第一个slot位置了</li>
</ul>
<p>类型安全的动态cast操作</p>
<ul>
<li>编译器做了额外的事情帮助程序员处理downcast带来的问题——如果转换失败，返回null而不是指向错误内存的指针</li>
<li>顺便总结一下三种cast操作的特点（const不用说了）
<ul>
<li>reinterpret_cast。仅指针。编译器解释。不修改格式。不安全。</li>
<li>static_cast。继承。基本不用于指针，效率不高。不安全。</li>
<li>dynamic_cast。继承。运行时。指针或引用。安全。</li>
</ul>
</li>
<li>dynamic_cast的额外开销：执行期通过需要转换的指针获得类型描述
<ul>
<li>(( type_info* )( p->__vptr[0] ))->type_descriptor</li>
<li>拿到之后要交给一个内置的函数判断p指向的类型和这个类型描述是否相符</li>
<li>本来贝尔实验室的人准备就用type()类似这样的运算符实现dynamic_cast，但C++标委会的人认为这样做和static_cast就没区别了，体现不出来dynamic_cast需要的额外开销</li>
</ul>
</li>
</ul>
<p>重提：引用不是指针</p>
<ul>
<li>和指针不同，引用不能指向到0，所以dynamic_cast失败的时候，只能引发一个异常</li>
</ul>
<p>Typeid运算符</p>
<ul>
<li>typeid返回的是一个对于type_info的const reference</li>
<li>它的==运算符也是被重载的</li>
<li>type_info的实际结构包括的信息：类名、和其他type_info对象的位置关系、类原名、子类型信息等</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

