﻿<?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>Ks Home &#187; C/C++ 备忘</title>
	<atom:link href="http://www.ksarea.com/articles/tag/cc-%e5%a4%87%e5%bf%98/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ksarea.com</link>
	<description>King和Sha的小窝</description>
	<lastBuildDate>Tue, 25 May 2010 03:24:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>重载、覆盖、隐藏</title>
		<link>http://www.ksarea.com/articles/20080527_overload-override-hide.html</link>
		<comments>http://www.ksarea.com/articles/20080527_overload-override-hide.html#comments</comments>
		<pubDate>Tue, 27 May 2008 11:58:34 +0000</pubDate>
		<dc:creator>king</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[C/C++ 备忘]]></category>

		<guid isPermaLink="false">http://www.ksarea.com/articles/20080527_overload-override-hide.html</guid>
		<description><![CDATA[这里讲重载（overload）、覆盖（override）、隐藏是基于OOP的继承、多态来阐述。 三者有一点是完全相同的，那就是讨论的函数都是同名的。
1、重载比较好理解，是指与许存在多个同名函数，而这些函数的参数表不同（或者参数个数不同、或者参数类型不同、或者两者皆不同）。注意：仅仅是函数的返回值不同的重载，编译器是会嗷嗷叫的！ 
类成员函数被重载的特征：

相同的范围（在同一个类中）；
函数名字相同；
参数不同（或者参数个数不同、或者参数类型不同、或者两者皆不同）；
virtual 关键字可有可无。

这里要偏离下主题，备案一个刚刚获知的知识点。一直以来，我以为复制构造函数有以下两种重载原型：
Myclass(Myclass &#38;);
Myclass(const Myclass &#38;);
今天又学一手，还有第三种复制构造函数原型：
Myclass(volatile Myclass &#38;);
2、言归正传，而覆盖是指派生类函数覆盖基类函数，它总是和继承、多态扯上千丝万缕的关系，可谓你中有我，我中有你！它的特征如下：

不同的范围（分别位于派生类与基类）；
函数名字相同；
参数相同（vs2005里两个函数的返回值也要一样，否则报error）；
基类函数必须有virtual 关键字。

也就是说分别处于互为继承关系的类中，两个完全相同的一模一样的虚函数才有覆盖的概念！
看如下代码：
#include &#60;iostream&#62;
using namespace std;
class base{public:&#160;&#160;&#160; void f(int x) { cout&#60;&#60; &#8220;base::f(int)&#8221; &#60;&#60; endl; }&#160;&#160;&#160; void f(float y) { cout &#60;&#60; &#8220;base::f(float)&#8221; &#60;&#60; endl;}&#160;&#160;&#160; virtual void g(void) { cout &#60;&#60; &#8220;base::g(void)&#8221; &#60;&#60; endl; }};
class derived:public base{public:
&#160;&#160;&#160; //这里的virtual可要可不要，因为基类函数有virtual，继承类同名同参数函数自动加上virtual&#160;&#160;&#160; virtual void g(void) { cout &#60;&#60; &#8220;derived::g(void)&#8221; &#60;&#60; endl;}}; 
int [...]]]></description>
			<content:encoded><![CDATA[<p>这里讲重载（overload）、覆盖（override）、隐藏是基于OOP的继承、多态来阐述。 三者有一点是完全相同的，那就是讨论的函数都是同名的。</p>
<p><strong>1、</strong>重载比较好理解，是指与许存在多个同名函数，而这些函数的参数表不同（或者参数个数不同、或者参数类型不同、或者两者皆不同）。<font color="#ff0000">注意：仅仅是函数的返回值不同的重载，编译器是会嗷嗷叫的！ </font></p>
<p>类成员函数被重载的特征：</p>
<ul>
<li>相同的范围（在同一个类中）；</li>
<li>函数名字相同；</li>
<li>参数不同（或者参数个数不同、或者参数类型不同、或者两者皆不同）；</li>
<li>virtual 关键字可有可无。</li>
</ul>
<p>这里要偏离下主题，备案一个刚刚获知的知识点。一直以来，我以为复制构造函数有以下两种重载原型：
<p>Myclass(Myclass &amp;);
<p>Myclass(const Myclass &amp;);
<p>今天又学一手，还有第三种复制构造函数原型：
<p>Myclass(volatile Myclass &amp;);
<p><strong>2、</strong>言归正传，而覆盖是指派生类函数覆盖基类函数，它总是和继承、多态扯上千丝万缕的关系，可谓你中有我，我中有你<img alt="Open-mouthed" src="http://messenger.msn.com/MMM2006-04-19_17.00/Resource/emoticons/teeth_smile.gif">！它的特征如下：
<ul>
<li>不同的范围（分别位于派生类与基类）；</li>
<li>函数名字相同；</li>
<li>参数相同（vs2005里两个函数的返回值也要一样，否则报error）；</li>
<li>基类函数必须有virtual 关键字。</li>
</ul>
<p>也就是说分别处于互为继承关系的类中，两个完全相同的一模一样的虚函数才有覆盖的概念！
<p>看如下代码：
<p>#include &lt;iostream&gt;
<p>using namespace std;
<p>class base<br />{<br />public:<br />&nbsp;&nbsp;&nbsp; void f(int x) { cout&lt;&lt; &#8220;base::f(int)&#8221; &lt;&lt; endl; }<br />&nbsp;&nbsp;&nbsp; void f(float y) { cout &lt;&lt; &#8220;base::f(float)&#8221; &lt;&lt; endl;}<br />&nbsp;&nbsp;&nbsp; virtual void g(void) { cout &lt;&lt; &#8220;base::g(void)&#8221; &lt;&lt; endl; }<br />};
<p>class derived:public base<br />{<br />public:</p>
<p>&nbsp;&nbsp;&nbsp; //这里的virtual可要可不要，因为基类函数有virtual，继承类同名同参数函数自动加上virtual<br />&nbsp;&nbsp;&nbsp; <strong>virtual </strong>void g(void) { cout &lt;&lt; &#8220;derived::g(void)&#8221; &lt;&lt; endl;}<br />}; </p>
<p>int main()<br />{<br />&nbsp;&nbsp;&nbsp; derived d;<br />&nbsp;&nbsp;&nbsp; base * pb=&amp;d;<br />&nbsp;&nbsp;&nbsp; pb-&gt;f(10);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //base::f(int)<br />&nbsp;&nbsp;&nbsp; pb-&gt;f(3.1415f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //base::f(float)<br />&nbsp;&nbsp;&nbsp; pb-&gt;g();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //derived::g(void)<br />}</p>
<p>base类中void f(int x)和void f(float y)就属于重载，而derived::g(void)就是覆盖base::g(void)。
<p>3、前面两者还算好区分，C++里的隐藏才是令人迷惑。隐藏指派生类的函数<strong>屏蔽</strong>了与其同名的基类函数，其规则如下：
<ul>
<li>如果派生类的函数与基类的函数同名，但是参数不同。此时，不论有无virtual关键字，基类的函数将被隐藏（注意别与重载混淆）。</li>
<li>如果派生类的函数与基类的函数同名，并且参数也相同，但是基类函数没有virtual关键字。此时，基类的函数被隐藏（注意别与覆盖混淆）。</li>
</ul>
<p>这两句话可以这么理解：通过继承类对象、指针或者引用没有办法调用到基类中的那个函数，这叫继承类隐藏了基类的函数；反之亦然！也就是说隐藏在继承层次中是相互的，你隐藏我，我也隐藏你！</p>
<p>一句话概括：如果两个函数分别在继承关系的类中，只要不是覆盖关系，那么一定就是屏蔽关系！！</p>
<p>将上述两个类代码换成如下形式：</p>
<p>class base<br />{<br />public:<br />&nbsp;&nbsp;&nbsp; void f(int x) { cout&lt;&lt; &#8220;base::f(int)&#8221; &lt;&lt; endl; }<br />&nbsp;&nbsp;&nbsp; void g(void) { cout &lt;&lt; &#8220;base::g(void)&#8221; &lt;&lt; endl; }<br />};
<p>class derived:public base<br />{<br />public:</p>
<p>&nbsp;&nbsp;&nbsp; void f(float y) { cout &lt;&lt; &#8220;base::f(float)&#8221; &lt;&lt; endl;}<br />&nbsp;&nbsp;&nbsp; void g(void) { cout &lt;&lt; &#8220;derived::g(void)&#8221; &lt;&lt; endl;}<br />}; </p>
<p>这里derived::f(float y)就是第一种方式隐藏base::f(int x)；derived::g(void)就是第二种方式隐藏base::g(void)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ksarea.com/articles/20080527_overload-override-hide.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#pragma预处理指令</title>
		<link>http://www.ksarea.com/articles/20080527_pragma-preop.html</link>
		<comments>http://www.ksarea.com/articles/20080527_pragma-preop.html#comments</comments>
		<pubDate>Tue, 27 May 2008 05:18:48 +0000</pubDate>
		<dc:creator>king</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[C/C++ 备忘]]></category>

		<guid isPermaLink="false">http://www.ksarea.com/articles/20080527_pragma%e9%a2%84%e5%a4%84%e7%90%86%e6%8c%87%e4%bb%a4.html</guid>
		<description><![CDATA[在所有编译预处理指令中，#pragma指令是最复杂的，它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。它的格式一般为：#pragma para&#160; 其中para为参数。下面罗列一些我见到过的参数。
1.message 参数 
使用方法：#pragma message(&#8220;文本消息&#8221;)
作用：当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。注意：这里的编译输出窗口不是指打印程序输出结果的那个黑黑控制台窗口，而是指IDE下面输出编译信息，例如：给你报编译错误的那个窗口。
2. warning 参数
例如：#pragma warning(diable:4507;once:4385;error:164)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(disable:4507&#160; 34)&#160;&#160;&#160; //&#160; 不显示4507和34号警告信息&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(once:4385)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //&#160; 4385号警告信息仅报告一次&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(error:164)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //&#160; 把164号警告信息作为一个错误。&#160; 
同时这个pragma&#160; warning&#160; 也支持如下格式：&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(&#160; push&#160; [&#160; ,n&#160; ]&#160; )&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(&#160; pop&#160; )&#160; 这里n代表一个警告等级(1～4)。&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(&#160; push&#160; )保存所有警告信息的现有的警告状态。&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(&#160; push,&#160; n)保存所有警告信息的现有的警告状态，并且把全局警告&#160; 等级设定为n。&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #pragma&#160; warning(&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>在所有编译预处理指令中，#pragma指令是最复杂的，它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。它的格式一般为：#pragma para&nbsp; 其中para为参数。下面罗列一些我见到过的参数。</p>
<p>1.message 参数 </p>
<p>使用方法：#pragma message(&#8220;文本消息&#8221;)</p>
<p>作用：当编译器遇到这条指令时就在<strong>编译输出窗口</strong>中将消息文本打印出来。注意：这里的编译输出窗口不是指打印程序输出结果的那个黑黑控制台窗口，而是指IDE下面输出编译信息，例如：给你报编译错误的那个窗口。</p>
<p>2. warning 参数</p>
<p>例如：#pragma warning(diable:4507;once:4385;error:164)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(disable:4507&nbsp; 34)&nbsp;&nbsp;&nbsp; //&nbsp; 不显示4507和34号警告信息&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(once:4385)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; 4385号警告信息仅报告一次&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(error:164)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; 把164号警告信息作为一个错误。&nbsp; </p>
<p>同时这个pragma&nbsp; warning&nbsp; 也支持如下格式：&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; push&nbsp; [&nbsp; ,n&nbsp; ]&nbsp; )&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; pop&nbsp; )&nbsp; <br />这里n代表一个警告等级(1～4)。&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; push&nbsp; )保存所有警告信息的现有的警告状态。&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; push,&nbsp; n)保存所有警告信息的现有的警告状态，并且把全局警告&nbsp; <br />等级设定为n。&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; pop&nbsp; )向栈中弹出最后一个警告信息，在入栈和出栈之间所作的&nbsp; <br />一切改动取消。例如：&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; push&nbsp; )&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; disable&nbsp; :&nbsp; 4705&nbsp; )&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; disable&nbsp; :&nbsp; 4706&nbsp; )&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; disable&nbsp; :&nbsp; 4707&nbsp; )&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;&#8230;.&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #pragma&nbsp; warning(&nbsp; pop&nbsp; )&nbsp;&nbsp;&nbsp; <br />在这段代码的最后，重新保存所有的警告信息(包括4705，4706和4707)。</p>
<p>3. comment 参数</p>
<p>原型：<b>#pragma comment(</b> comment-type [<b>,"</b>commentstring<b>"</b>] <b>)</b></p>
<p>该指令将一个注释记录放入一个对象文件或可执行文件中。 常用的comment-type有lib、compiler等。</p>
<p>例如在我的大数运算库里使用的一条指令：#pragma&nbsp;&nbsp; comment(lib,&#8221;winmm.lib&#8221;)，目的就是导入winmm.lib库，连接器能连接这个库，以便能调用该静态库里的函数。</p>
<p>4. pack 参数</p>
<p>有如下几种形式：</p>
<p>#pragma pack()&nbsp;&nbsp;&nbsp;&nbsp; //取消对齐，恢复最原始缺省对齐</p>
<p>#pragma pack(n)&nbsp;&nbsp;&nbsp; /*指定按n字节对齐，其取值为1、2、4、8、16，默认是8，如果这个值比结构体成员的sizeof值小，那么该成员距结构体起始位置的偏移量应该以&nbsp;&nbsp; 此值为准，即是说，结构体成员的偏移量应该取二者的最小值，公式如下：<br />offsetof( item ) = min( n, sizeof( item ))&nbsp; */</p>
<p>#pragma pack(push)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //保存当前对其方式到packing stack</p>
<p>#pragma pack(push,n)&nbsp;&nbsp; 等效于 #pragma pack(push)&nbsp; #pragma pack(n)&nbsp; //n=1,2,4,8,16保存当前对齐方式，设置按n字节对齐</p>
<p>#pragma pack(pop)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //packing stack 出栈，并将对其方式设置为出栈的对齐方式</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ksarea.com/articles/20080527_pragma-preop.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
