﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-思勤无邪</title><link>http://www.cppblog.com/andxie99/</link><description>上学时，因我年龄最小，个头也最小，上课时，就像大猩猩堆里的猴一般。如今，这猴偶尔也把最近的一些情况写在这里。</description><language>zh-cn</language><lastBuildDate>Mon, 06 Apr 2026 18:54:02 GMT</lastBuildDate><pubDate>Mon, 06 Apr 2026 18:54:02 GMT</pubDate><ttl>60</ttl><item><title>我的emacs 配置，做个备份</title><link>http://www.cppblog.com/andxie99/archive/2010/11/17/133913.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Wed, 17 Nov 2010 12:59:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2010/11/17/133913.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/133913.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2010/11/17/133913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/133913.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/133913.html</trackback:ping><description><![CDATA[;(require 'color-theme)<br>;(color-theme-initialize)<br>;(color-theme-tty-dark)<br>;(color-theme-comidia)<br>;(color-theme-dark-laptop)<br><br>;;;; 显示行号：<br>(require 'linum)<br>(global-linum-mode t)<br>(column-number-mode t)<br>(setq column-number-mode t)<br>(setq line-number-mode t)<br><br>(set-face-background 'default "black")<br>(set-face-foreground 'default "wheat")<br>(set-cursor-color "white")<br><br>;;;; 显示时间<br>(setq display-time-24hr-format t)<br>(setq display-time-day-and-date t)<br>(display-time)<br><br>;;;; 关闭启动画面<br>(setq inhibit-startup-message t)<br><br>;;;;设置大的kill ring<br>(setq kill-ring-max 150)<br><br>(require 'xcscope)<br><br>;;;;备份策略<br>(setq backup-directory-alist '(("" . "~/backup/emacs/backup")))<br>(setq-default make-backup-file t)<br>(setq make-backup-file t)<br><br>(setq make-backup-files t)<br>(setq version-control t)<br>(setq kept-old-versions 2)<br>(setq kept-new-versions 10)<br>(setq delete-old-versions t)<br><br><br>;;;;C/C++语言启动时自动加载semantic对/usr/include的索引数据库<br>(setq semanticdb-search-system-databases t)<br>&nbsp; (add-hook 'c-mode-common-hook<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (lambda ()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setq semanticdb-project-system-databases<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (list (semanticdb-create-database<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; semanticdb-new-database-class<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "/usr/include")))))<br><br>;; project root path<br>(setq semanticdb-project-roots<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (list<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (expand-file-name "/")))<br>;; 避免semantic占用CPU过多<br>(setq-default semantic-idle-scheduler-idle-time 432000)<br><br>(defun my-indent-or-complete ()<br>&nbsp;&nbsp; (interactive)<br>&nbsp;&nbsp; (if (looking-at "\\&gt;")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (hippie-expand nil)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (indent-for-tab-command)))<br>(autoload 'senator-try-expand-semantic "senator")<br><br>(setq hippie-expand-try-functions-list<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; senator-try-expand-semantic<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-dabbrev<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-dabbrev-visible<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-dabbrev-all-buffers<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-dabbrev-from-kill<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-list<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-list-all-buffers<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-line<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-line-all-buffers<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-complete-file-name-partially<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-complete-file-name<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try-expand-whole-kill<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>)<br><br>(defun linux-c-mode ()<br>&nbsp; "C mode with adjusted defaults for use with the Linux kernel."<br>&nbsp; (interactive)<br>&nbsp; (c-mode)<br>&nbsp; (c-set-style "K&amp;R")<br>&nbsp; (setq tab-width 8)<br>&nbsp; (setq indent-tabs-mode t)<br>&nbsp; (setq c-basic-offset 8))<br><br><br>;; c-mode公共设置<br>(defun my-c-mode-common-hook ()<br>&nbsp; (interactive)<br>&nbsp; ;(c-mode)<br>&nbsp; ;(c-set-style "K&amp;R")<br>&nbsp; (setq tab-width 8)<br>&nbsp; (setq indent-tabs-mode t)<br>&nbsp; (setq c-basic-offset 8)<br>&nbsp; (hs-minor-mode t)<br><br>&nbsp; ;;; hungry-delete and auto-newline<br>&nbsp; ;;(c-toggle-auto-hungry-state 1)<br>&nbsp; ;;按键定义<br>&nbsp; (define-key c-mode-base-map [(control \`)] 'hs-toggle-hiding)<br>&nbsp; (define-key c-mode-base-map [(return)] 'newline-and-indent)<br>&nbsp; (define-key c-mode-base-map [(f7)] 'compile)<br>&nbsp; (define-key c-mode-base-map [(f8)] 'ff-get-other-file)<br>&nbsp; (define-key c-mode-base-map [(f5)] 'gud-go)<br>&nbsp; (define-key c-mode-base-map [(f10)] 'gud-next)<br>&nbsp; (define-key c-mode-base-map [(f11)] 'gud-step)<br>&nbsp; <br>&nbsp; (define-key c-mode-base-map [(meta \`)] 'c-indent-command)<br>;;&nbsp; (define-key c-mode-base-map [(tab)] 'hippie-expand)<br>&nbsp; (define-key c-mode-base-map [(tab)] 'my-indent-or-complete)<br>&nbsp; (define-key c-mode-base-map [(meta ?/)] 'semantic-ia-complete-symbol-menu)<br>&nbsp; ;;预处理设置<br>&nbsp; (setq c-macro-shrink-window-flag t)<br>&nbsp; (setq c-macro-preprocessor "cpp")<br>&nbsp; (setq c-macro-cppflags " ")<br>&nbsp; (setq c-macro-prompt-flag t)<br>&nbsp; (setq hs-minor-mode t)<br>&nbsp; (setq abbrev-mode t))<br>(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)<br><br>;; C 语言设置<br>(defun my-c-mode-hook ()<br>&nbsp; (c-set-style "cc-mode"))<br>(add-hook 'c-mode-hook 'my-c-mode-hook)<br><br>;; C++设置<br>(defun my-c++-mode-hook ()<br>&nbsp; (c-set-style "stroustrup"))<br>(add-hook 'c++-mode-hook 'my-c++-mode-hook)<br><br>;;;; CC-mode配置&nbsp; http://cc-mode.sourceforge.net/<br>(require 'cc-mode)<br>(c-set-offset 'inline-open 0)<br>(c-set-offset 'friend '-)<br>(c-set-offset 'substatement-open 0)<br><br>;;;;根据后缀判断所用的mode<br>;;;;注意：我在这里把.h关联到了c++-mode<br>(setq auto-mode-alist<br>&nbsp;&nbsp;&nbsp; &nbsp; (append '(("\\.h$" . c++-mode)) auto-mode-alist))<br><br>;;;; Python Mode设置<br>;(add-to-list 'load-path "/home/caole/lib/emacs-lisp/python-mode-1.0")<br>;(require 'python-mode)<br>;;(require 'pycomplete)<br>;(require 'doctest-mode)<br><br>;;;; 注释配置<br>;(load-file "/home/caole/lib/emacs-lisp/gnome-doc.el")<br><br><br><br>(custom-set-variables<br>&nbsp; ;; custom-set-variables was added by Custom.<br>&nbsp; ;; If you edit it by hand, you could mess it up, so be careful.<br>&nbsp; ;; Your init file should contain only one such instance.<br>&nbsp; ;; If there is more than one, they won't work right.<br>&nbsp;'(ecb-layout-window-sizes (quote (("left9" (0.3170731707317073 . 0.9642857142857143)))))<br>&nbsp;'(ecb-options-version "2.40"))<br>(custom-set-faces<br>&nbsp; ;; custom-set-faces was added by Custom.<br>&nbsp; ;; If you edit it by hand, you could mess it up, so be careful.<br>&nbsp; ;; Your init file should contain only one such instance.<br>&nbsp; ;; If there is more than one, they won't work right.<br>&nbsp;)<br>&nbsp;<br><img src ="http://www.cppblog.com/andxie99/aggbug/133913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2010-11-17 20:59 <a href="http://www.cppblog.com/andxie99/archive/2010/11/17/133913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网上看到的一个面试题：利用星号输出画一个任意大小的圆</title><link>http://www.cppblog.com/andxie99/archive/2010/10/16/130177.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 16 Oct 2010 15:41:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2010/10/16/130177.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/130177.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2010/10/16/130177.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/130177.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/130177.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #008000;">/*</span><span style="color: #008000;">利用星号输出画一个任意大小的圆</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">math.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;max(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;a,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;b)<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;a&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;b&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;a&nbsp;:&nbsp;b;<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;print_char(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x1,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x2)<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i;<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;计算这一行的宽度，终端最多显示80列</span><span style="color: #008000;"><br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;max(x1,&nbsp;x2)&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">80</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">80</span><span style="color: #000000;">&nbsp;:&nbsp;n;<br></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;n;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;x1&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;x2)<br></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">*</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;print_circle(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;r)<br></span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x1,&nbsp;x2,&nbsp;y;<br></span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;d&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;r;<br></span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;offset;<br></span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(y&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;y&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;d;&nbsp;y</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br></span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="color: #008080;">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">终端字符宽高比为2:1</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #008080;">34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)(</span><span style="color: #000000;">0.5</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;sqrt((</span><span style="color: #0000ff;">double</span><span style="color: #000000;">)(r</span><span style="color: #000000;">*</span><span style="color: #000000;">r&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;(y</span><span style="color: #000000;">-</span><span style="color: #000000;">r)</span><span style="color: #000000;">*</span><span style="color: #000000;">(y</span><span style="color: #000000;">-</span><span style="color: #000000;">r)))</span><span style="color: #000000;">*</span><span style="color: #000000;">2.0</span><span style="color: #000000;">);<br></span><span style="color: #008080;">35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;d&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;offset;<br></span><span style="color: #008080;">36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x2&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;d&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;offset;<br></span><span style="color: #008080;">37</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print_char(x1,&nbsp;x2);<br></span><span style="color: #008080;">38</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080;">39</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">40</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">41</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argn,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">argv[])<br></span><span style="color: #008080;">42</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">43</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;r&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">;<br></span><span style="color: #008080;">44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(argn&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br></span><span style="color: #008080;">45</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;atoi(argv[</span><span style="color: #000000;">1</span><span style="color: #000000;">]);<br></span><span style="color: #008080;">46</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="color: #008080;">47</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;print_circle(r);<br></span><span style="color: #008080;">48</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br></span><span style="color: #008080;">49</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">50</span>&nbsp;<span style="color: #000000;"></span></div>
<br><img src ="http://www.cppblog.com/andxie99/aggbug/130177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2010-10-16 23:41 <a href="http://www.cppblog.com/andxie99/archive/2010/10/16/130177.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux kernel map</title><link>http://www.cppblog.com/andxie99/archive/2010/08/28/125081.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 28 Aug 2010 13:43:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2010/08/28/125081.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/125081.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2010/08/28/125081.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/125081.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/125081.html</trackback:ping><description><![CDATA[<img src="http://www.cppblog.com/images/cppblog_com/andxie99/LKM21_2048.png" border="0"><br><br>来源：http://www.linuxdriver.co.il/kernel_map<br><br> <img src ="http://www.cppblog.com/andxie99/aggbug/125081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2010-08-28 21:43 <a href="http://www.cppblog.com/andxie99/archive/2010/08/28/125081.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mozilla 源码</title><link>http://www.cppblog.com/andxie99/archive/2010/07/23/121148.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Fri, 23 Jul 2010 15:14:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2010/07/23/121148.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/121148.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2010/07/23/121148.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/121148.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/121148.html</trackback:ping><description><![CDATA[包括firefox源码，文档等:<br>http://releases.mozilla.org/pub/mozilla.org/<br>ftp://ftp.mozilla.org/pub/mozilla.org<br><br><br>source code directories overview:<br>https://developer.mozilla.org/en/Source_code_directories_overview<br><br> <img src ="http://www.cppblog.com/andxie99/aggbug/121148.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2010-07-23 23:14 <a href="http://www.cppblog.com/andxie99/archive/2010/07/23/121148.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 利用异常来确保资源释放</title><link>http://www.cppblog.com/andxie99/archive/2010/06/06/117255.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 06 Jun 2010 01:21:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2010/06/06/117255.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/117255.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2010/06/06/117255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/117255.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/117255.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; C++ 一般会在构造函数里分配资源，在析构函数里释放资源。但当程序／函数不正常退出时，C＋＋ 不能保证析构函数会被调用，这时，可以利用异常，在程序／函数需要退出时，扔出异常，在异常处理里退出程序／函数，这样可以使在函数调用堆栈上构造的对象正确析构。<br>&nbsp;&nbsp;&nbsp; 示例代码（摘自advanced linux programming 4.3.2 Thread Cleanup in C++）：<br>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">pthread.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ThreadExitException<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; /*</span><span style="color: #008000;">&nbsp;Create&nbsp;an&nbsp;exception-signaling&nbsp;thread&nbsp;exit&nbsp;with&nbsp;RETURN_VALUE.&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">ThreadExitException&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;return_value)<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">:&nbsp;thread_return_value_&nbsp;(return_value)<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">}<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;Actually&nbsp;exit&nbsp;the&nbsp;thread,&nbsp;using&nbsp;the&nbsp;return&nbsp;value&nbsp;provided&nbsp;in&nbsp;the&nbsp;constructor.&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;DoThreadExit&nbsp;()<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">pthread_exit&nbsp;(thread_return_value_);<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">}<br></span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;The&nbsp;return&nbsp;value&nbsp;that&nbsp;will&nbsp;be&nbsp;used&nbsp;when&nbsp;exiting&nbsp;the&nbsp;thread.&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;thread_return_value_;<br>};<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;do_some_work&nbsp;()<br>{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;Do&nbsp;some&nbsp;useful&nbsp;things&nbsp;here<img src="http://www.cppblog.com/Images/dot.gif">&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br><br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(should_exit_thread_immediately&nbsp;())<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;ThreadExitException&nbsp;(</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;thread&#8217;s&nbsp;return&nbsp;value&nbsp;=&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;">&nbsp;NULL);<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">}<br>}<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;thread_function&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">)<br>{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">do_some_work&nbsp;();<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">}<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;"></span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(ThreadExitException&nbsp;ex)&nbsp;{<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;Some&nbsp;function&nbsp;indicated&nbsp;that&nbsp;we&nbsp;should&nbsp;exit&nbsp;the&nbsp;thread.&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">ex.DoThreadExit&nbsp;();<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">}<br></span><span style="color: #008000;">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;NULL;<br>}<br><br></span></div>
<br><br><img src ="http://www.cppblog.com/andxie99/aggbug/117255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2010-06-06 09:21 <a href="http://www.cppblog.com/andxie99/archive/2010/06/06/117255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈如何学习linux</title><link>http://www.cppblog.com/andxie99/archive/2010/05/09/114915.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 09 May 2010 06:18:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2010/05/09/114915.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/114915.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2010/05/09/114915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/114915.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/114915.html</trackback:ping><description><![CDATA[原文：<a href="http://xiaoao808.javaeye.com/blog/458157">http://xiaoao808.javaeye.com/blog/458157</a><br><br>一.为什么要学linux? <br><br>当然最重要是爱好和兴趣！如果你这种必要学，或者根本不喜欢，请不要浪费时间，你学也学不好！ <br><br>二.起步 <br><br>你应该为自己创造一个学习linux的环境--在电脑上装一个linux或unix <br>问题1：版本的选择 <br><br>北美用redhat,欧洲用SuSE,桌面mandrake较多，而debian是技术最先进的linux <br>开发人员中用debian的最多，其次是redhat,从全球linux各应用领域市场份额来看 <br>无疑redhat是最多的，此外还有很多出名的发行版本，不再列举。 <br>对于初学linux的人来说，我建议是使用redhat,原因如下： <br>1）现在很多书都是以redhat为例讲的，为了与书本协调一致 <br>2）周围的人都用redhat,交流比较方便 <br>3）redhat应用范围广，有典型性和代表性 <br>4）它易于使用和安装，我们没有必要把时间浪费在&#8220;装系统&#8221;上 <br>而应集中精力学习最有用的东西。 <br><br>//注：现在觉得RH很死板，AS,ES等用在服务器上或许不错， <br>Personal desktop用mandrake,debian,suse都不错，笔者现在用Mandrake,因为她长得漂亮 <br><br>如果你并不打算深入学习linux，而是有诸如适应北京市政府办公平台迁移到 <br>linux上这种需要，那么中软，红旗等中文linux是不错的选择 <br><br>我强烈建议：自己亲自动手把linux装到你的硬盘上， <br>你必须学会独立安装linux系统的技能，对于现在的版本来说，其实跟装WinXP一样简单 <br><br>从此现在开始，请不要以windows的工作方式来考虑问题， <br>应该尝试挖掘linux身上的&#8220;天才unix&#8221;的气质。 <br><br>三.进阶 <br>掌握至少50个以上的常用命令 <br>理解shell管道"|",文件流重定向"&gt;"及追加"&gt;&gt;"等 <br>熟悉Gnome/KDE等X-windows桌面环境操作 <br>掌握.tgz.rpm.biz等软件包的常用安装方法 <br>学习添加外设，安装设备驱动程序（比如modem) <br>熟悉Grub/Lilo引导器及简单的修复操作 <br>熟悉系统固有目录的名称及公用 <br>学会用mount命令访问其他文件系统 <br>了解vi,gcc,gdb等常用编辑器，编译器，调试器 <br>学习linux环境下的简单组网 <br><br>建议：买一本不需要太厚的linux教材，大致可以满足要求 <br>//现在的书越来越多了，还带很多图，我当时可没这么多书：） <br><br>四.高级应用 <br><br>澄清一些概念： <br>linux的普通操作与真正的系统管理不能相提并论，后者需要很多知识 <br><br>我个人认为比较重要几种linux语言 <br>1.英语 <br>即使你不学linux，我也强烈建议你学好英文[U.S.english] <br>因为实质上计算机语言就是英文和字符,所谓的多国语言只是外部包装 <br>你必须能无障碍的阅读大量的英文技术文档 <br>在搜索引擎找到的英文网站和网页中熟练的检索 <br>最好能有用英文直接交流的能力， <br>摆脱了这个障碍，你的学习和理解速度就能快很多，你就有机会拉开和别人的差距 <br><br>2.shell[sed/awk] <br>shell是命令解释器，是内核与用户界面交流通道，shell写的小脚本有点类似于win下的.bat <br>但shell比.bat强大的多，shell不只是解释命令，更是一种编程语言，有时候几百行的c用shell <br>几十行就能代替完成工作，因为shell的工作方式建立在系统已有的众多应用程序之上 <br>这也是CS中的一个重要思想。 <br>此外，shell可以实现工作自动化，这个概念也比较重要 <br>sed,awk用来处理文本，历来很常用 <br><br>3.Perl/PHP <br>漂亮的脚本， CGI的首选，比ASP好，应用面很广 <br><br>4.C\C++ <br>C、C++是linux/unix的核心语言，系统代码都是C写的 <br><br>5.ASM <br>系统底层及内核，硬件，设备驱动程序，嵌入式开发都需要 <br>//走核心路线的话，才c\c++,asm最重要 <br><br>6.Java,Python,Tcl,XML <br><br>*系统管理篇 <br>在熟悉linux的基础上还需要掌握至少一种unix <br>我首推Solaris，其次是FreeBSD <br>比如运营级系统一般是Solaris+Oracle/DB2之类的 <br>学习apache,ssh,sendmail/Qmail,proftp/vsftp,Samba,Squid,MySQL/PostgreSQL/Oracle,Bind <br>等各种应用服务器的构架及电子商务的应用 <br>熟悉TCP/IP协议族，学习诸如apache+php+proftp+mysql+quota的实现以及大型局域网，分布式集群 <br>等各种企业级应用解决方案 <br>熟悉多用户管理，数据库管理，文件系统，逻辑存储管理，日志分析，备份与灾难数据修复 <br>系统补丁，内核升级，以及在此基础上的防火墙构架等以保障系统安全在内的各种系统管理技能 <br><br>我觉得，如果在此基础上再掌握路由/交换设备便是一个不错的系统管理员 <br><br>各种基于linux的解决方案可参考相关书籍和文献，必要时用google或各大linux站点站内 <br>搜索引擎寻找最新文档，以避免错误和漏洞 <br>有几本技术大全和技术内幕我认为都是这方面不错的书 <br><br>*深入学习linux <br><br>我个人理解的读linux内核需要的基础： <br>在此之前,希望先把应用层的东西学一下,那样会比较好理解 <br>1.C <br>如果学过潭浩强的大学教科书(除了编几个数学模型好像什么也做不了的那种)， <br>建议再看一下 <br>《The C Programming Language》Second Edition这本圣经 <br>/*如果想学缓冲区溢出，这点C的功力可能是不够的*/ <br>还有,,, <br>反正经典书看多了是没有坏处的 <br><br>2.asm (AT&amp;T语法，保护模式) <br>保护模式下的比较复杂，基本上每本讲内核的书都会有介绍 <br>有80x86 Intel语法的基础就行， <br>有兴趣可以看看Intel的官方**** <br><br>3.数据结构（离散数学） <br>计算机专业的核心课程，重要性我就不说了 <br><br>4.操作系统原理 <br>看懂这个再去读linux吧 <br><br>5.微机原理/组成原理（数字电路） <br>底层直接和硬件打交道，所以这个也要 <br><br>6.了解linux/unix <br>我想至少你要会操作吧，了解unix的API <br><br>7.软件工程/编译原理 <br><br>这方面的经典书去<a href="http://www.china-pub.com/" target=_blank><u><font color=#108ac6>www.china-pub.com</font></u></a>可以搜到很多 <br>我觉得APUE这种书不适合初学者，还是先看看UPE之类的吧 <br><br>APUE: <br>《advanced　programming　in　the　unix　environment》 <br>《unix环境高级编程》 <br>作者：W.Richard.Stevens共有6本经典书，尊为&#8220;圣经&#8221; <br>他的书为全世界黑客所拜读！ <br><br>UPE:《unix　programming　environment》 <br>《unix编程环境》比较适合初学者的，深入浅出， <br>其中有一些比较重要的思想 <br>另外,介绍linux下应用层编程的书也有很多,比如 <br>,redhat,redflag出的书........... <br>经典书还有很多很多...... <br>操作系统：设计与实现　//交大的考研参考书目，讲Minix的 <br>unix操作系统设计 <br>4.4BSD操作系统设计与实现 <br>昂莱氏unix源代码分析 <br>ulk:understanding the linux kernel (2nd)深入理解linux内核 <br>linux设备驱动程序 (2nd) <br>linux内核源代码情景分析 <br>保护方式下的80386及其编程 
<img src ="http://www.cppblog.com/andxie99/aggbug/114915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2010-05-09 14:18 <a href="http://www.cppblog.com/andxie99/archive/2010/05/09/114915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用VS 搭建汇编 IDE</title><link>http://www.cppblog.com/andxie99/archive/2009/11/22/101599.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 22 Nov 2009 04:25:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2009/11/22/101599.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/101599.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2009/11/22/101599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/101599.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/101599.html</trackback:ping><description><![CDATA[推荐一篇文章，Assembly Language for Intel-Based Computers 的作者写的。<a href="http://kipirvine.com/asm/gettingStarted/index.htm"><br>http://kipirvine.com/asm/gettingStarted/index.htm</a>
<img src ="http://www.cppblog.com/andxie99/aggbug/101599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2009-11-22 12:25 <a href="http://www.cppblog.com/andxie99/archive/2009/11/22/101599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>各类标准硬件接口图</title><link>http://www.cppblog.com/andxie99/archive/2009/09/19/96726.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 19 Sep 2009 13:12:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2009/09/19/96726.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/96726.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2009/09/19/96726.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/96726.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/96726.html</trackback:ping><description><![CDATA[<img  src="http://www.cppblog.com/images/cppblog_com/andxie99/computer-hardware-chart1.jpg" border="0"><br><br>详细请看：http://www.technibble.com/computer-hardware-chart/<br><br><img src ="http://www.cppblog.com/andxie99/aggbug/96726.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2009-09-19 21:12 <a href="http://www.cppblog.com/andxie99/archive/2009/09/19/96726.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>妙语摘录</title><link>http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Mon, 01 Oct 2007 13:01:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/33303.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/33303.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/33303.html</trackback:ping><description><![CDATA[<br>&nbsp;&nbsp;&nbsp; 整理资料，于G:\我的秘书\妙语下发现很多平时收集的认为不错的词句，整理如下，以后也会随时更新的。<br><br>&nbsp;&nbsp;&nbsp; <strong>&#8220;大学者，非谓有大楼之谓也，有大师之谓也。&#8221;</strong>&nbsp; ——清华老校长梅贻琦的治校名言。<br><br>林锐&nbsp;&nbsp;&nbsp; 《软件工程思想》中：<br>&nbsp;&nbsp;&nbsp; <strong>就象蒸出一笼馒头，在上面插一朵鲜花，本想弄点诗情画意，却让人误以为那是一堆热气腾腾的牛粪。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——讲述可理解性与简洁性时用的比喻。&nbsp;<br><br>&nbsp;&nbsp;&nbsp; <strong>人分四类——人物，人才，人手，人渣。</strong>&nbsp;&nbsp;&nbsp; ——可行性分析的要素中人这一要素时的论述 <br><br>&nbsp;&nbsp;&nbsp; <strong>举杭州西湖的例子吧。西湖的一些景点收门票，卖纪念品，一年不多的经营收入，只够用来打扫卫生、修修补补、种树植草。但西湖有白居易、苏东坡巨大的贡献，千年累积的&#8220;人文、历史、地理&#8221;价值何止千百亿。假设杭州西湖上市，起价1亿元人民币，真不知道有多少人来争抢，股值当然会狂升千百倍。而我家乡的一个鱼塘也叫&#8220;西湖&#8221;，主人从来不幻想他的&#8220;西湖&#8221;值多少个亿，但他知道卖不出鱼就会贫穷，一天不争几元钱就会挨饿。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——论述为什么一个固定资产可以被忽略的，几乎没有营业利润的Internet企业，可以有极高的股市价值，并且市值不停上涨。 <br><br>&nbsp;&nbsp;&nbsp; <strong>我认为Java好比是C++的外甥，虽然不是直接遗传的，但也几分象样。外甥在舅舅身上玩耍时洒了一泡尿，俩人不该为此而争吵。&nbsp;&nbsp;&nbsp; </strong>——关于编程语言 <br><br>&nbsp;&nbsp;&nbsp; <strong>有一次文学考试，问高尔基是哪国人。一考生乐极而吟：&#8220;尔基啊尔基，你若不姓高，我怎知你是中国人。&#8221;这是一种瞎猜法。如果这种方法用于软件测试，人累死也测不出什么结果来。</strong>&nbsp;&nbsp;&nbsp; ——软件测试 <br><br>&nbsp;&nbsp;&nbsp; <strong>都说急中生智，我不信。我认为大多数人着急了就会蛮干，早把&#8220;智&#8221;丢到脑后。不仅人如此，动物也如此。</strong>&nbsp;&nbsp;&nbsp; ——论述软件改错时不可蛮干&nbsp;<br><br>&nbsp;&nbsp;&nbsp;<strong> 抽象是有选择的忽略。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——C++深思录（Ruminations on C++中文版）<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; <strong>有的情况下，现在的折衷方案比未来的理想方案好得多。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——C++深思录（Ruminations on C++中文版） <br><br>&nbsp;&nbsp;&nbsp; <strong>真正的专业人员会将其所有的正规训练和经验技巧都专注于每一个所输入的按键上。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——《C++程序调试实用手册》<br><br>&nbsp;&nbsp;&nbsp; <strong>所谓好的注释就是既不至于侮辱一个程序员的智力，也不放过对任何复杂代码的解释。&nbsp;</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——《C++程序调试实用手册》<br><br>&nbsp;&nbsp;&nbsp; <strong>工具只有获取结果的手段，如果你只注意手段而忽视结果，那你就是在浪费时间。</strong><br>
<img src ="http://www.cppblog.com/andxie99/aggbug/33303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-10-01 21:01 <a href="http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>聊聊封装、继承</title><link>http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 21 Jul 2007 08:18:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/28494.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/28494.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/28494.html</trackback:ping><description><![CDATA[&nbsp;
<p>&nbsp;</p>
<p align=left><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在</span><span>C++</span><span>中封装的概念是把一个对象的外观接口同实际工作方式（实现）分离开来，但是</span><span>C++</span><span>的封装是不完全的，</span><span>编译器必须知道一个对象的所有部分的声明，以便创建和管理它。我们可以想象一种只需声明一个对象的公共接口部分的编程语言，而将私有的实现部分隐藏起来。</span><span>C + +</span><span>在编译期间要尽可能多地做静态类型检查。这意味着尽早捕获错误，也意味着程序具有更高的效率。然而这对私有的实现部分来说带来两个影响：一是即使程序员不能轻易地访问实现部分，但他可以看到它；二是造成一些不必要的重复编译<span>。</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>然而</span><span>C++</span><span>并没有将这个原则应用到二进制层次上，这是因为</span><span>C++</span><span>的类既是描述了一个接口同时也描述了实现的过程</span><span>,</span><span>示例如下：</span></p>
<p><span>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyString<br><img id=Codehighlighter1_16_172_Open_Image onclick="this.style.display='none'; Codehighlighter1_16_172_Open_Text.style.display='none'; Codehighlighter1_16_172_Closed_Image.style.display='inline'; Codehighlighter1_16_172_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_16_172_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_16_172_Closed_Text.style.display='none'; Codehighlighter1_16_172_Open_Image.style.display='inline'; Codehighlighter1_16_172_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_16_172_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_16_172_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;m_cch;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">m_psz;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CMyString(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CMyString();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Length()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Index(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p></span>&nbsp;</p>
<p>&nbsp;</p>
<p><span>CMyStirng</span><span>对外过多的暴露了内存布局实现的细节，这些信息过度的依赖于这些成员变量的大小和顺序，从而导致了客户过度依赖于可执行代码之间的二进制耦合关系，这样的接口不利于跨语言跨平台的软件开发和移植。</span></p>
<p>&nbsp;</p>
<p><strong><span>1.1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle-Body</span></strong><span>模式</span><strong></strong></p>
<p>&nbsp;</p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>解决这个问题的技术有一种叫句柄类（ </span><span>handle classes</span><span>）</span><span>。有关实现的任何东西都消失了，只剩一个单一的指针&#8220;</span><strong><span>m_pThis</span></strong><span>&#8221;。该指针指向一个结构，该结构的定义与其所有的成员函数的定义都出现在实现文件中。这样，只要接口部分不改变，头文件就不需变动。而实现部分可以按需要任意更动，完成后只要对实现文件进行重新编译，然后再连接到项目中。</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面是</span></span><span>这项技术的简单例子。头文件中只包含公共的接口和一个简单的没有完全指定的类指针。</span></p>
<p align=left>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyStringHandle<br><img id=Codehighlighter1_22_201_Open_Image onclick="this.style.display='none'; Codehighlighter1_22_201_Open_Text.style.display='none'; Codehighlighter1_22_201_Closed_Image.style.display='inline'; Codehighlighter1_22_201_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_22_201_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_201_Closed_Text.style.display='none'; Codehighlighter1_22_201_Open_Image.style.display='inline'; Codehighlighter1_22_201_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_22_201_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_22_201_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyString；<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CMyString&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">m_pThis;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CMyStringHandle&nbsp;(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">&nbsp;CMyStringHandle&nbsp;();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Length()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Index(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">；<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CMyStringHandle::&nbsp;CMyStringHandle(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>:m_pThis(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CMyString(psz));<br><img id=Codehighlighter1_286_288_Open_Image onclick="this.style.display='none'; Codehighlighter1_286_288_Open_Text.style.display='none'; Codehighlighter1_286_288_Closed_Image.style.display='inline'; Codehighlighter1_286_288_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_286_288_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_286_288_Closed_Text.style.display='none'; Codehighlighter1_286_288_Open_Image.style.display='inline'; Codehighlighter1_286_288_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_286_288_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_286_288_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CMyStringHandle::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">&nbsp;CMyStringHandle()<br><img id=Codehighlighter1_328_349_Open_Image onclick="this.style.display='none'; Codehighlighter1_328_349_Open_Text.style.display='none'; Codehighlighter1_328_349_Closed_Image.style.display='inline'; Codehighlighter1_328_349_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_328_349_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_328_349_Closed_Text.style.display='none'; Codehighlighter1_328_349_Open_Image.style.display='inline'; Codehighlighter1_328_349_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_328_349_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_328_349_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;delete&nbsp;m_pThis;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;CMyStringHandle::Length()<br><img id=Codehighlighter1_382_412_Open_Image onclick="this.style.display='none'; Codehighlighter1_382_412_Open_Text.style.display='none'; Codehighlighter1_382_412_Closed_Image.style.display='inline'; Codehighlighter1_382_412_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_382_412_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_382_412_Closed_Text.style.display='none'; Codehighlighter1_382_412_Open_Image.style.display='inline'; Codehighlighter1_382_412_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_382_412_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_382_412_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_pThis</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Length();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;CMyStringHandle::Index(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)<br><img id=Codehighlighter1_459_490_Open_Image onclick="this.style.display='none'; Codehighlighter1_459_490_Open_Text.style.display='none'; Codehighlighter1_459_490_Closed_Image.style.display='inline'; Codehighlighter1_459_490_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_459_490_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_459_490_Closed_Text.style.display='none'; Codehighlighter1_459_490_Open_Image.style.display='inline'; Codehighlighter1_459_490_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_459_490_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_459_490_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_pThis</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Index(psz);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p align=left>&nbsp;</p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>这是所有客户程序员都能看到的。<br></span><strong><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class</span></strong><span> <strong><span>CMyString</span></strong></span><strong><span>；</span></strong></p>
<p align=left><span>是一个没有完全指定的类型说明或类声明（一个类的定义包含类的主体）。它告诉编译器，</span><span><span><strong>CMyString</strong></span></span><span>是一个结构的名字，但没有提供有关该结构的任何东西。这对产生一个指向结构的指针来说已经足够了。但我们在提供一个结构的主体部分之前不能创建一个对象。在这种技术里，包含具体实现的结构主体被隐藏在实现文件中。</span></p>
<p align=left>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在设计模式中，这就叫做</span><span>Handle-Body </span><span>模式，</span><strong><span>Handle-Body</span></strong><span>只含有一个实体指针，服务的数据成员永远被封闭在服务系统中。</span></p>
<p><strong><span>Handle-Body</span></strong><span>的布局结构永远不会随着实现类数据成员的加入或者删除或者修改而导致<strong><span>Handle-Body</span></strong>的修改，即<strong><span>Handle-Body</span></strong>协议不依赖于<span>C++</span>实现类的任何细节。这就有效的对用户的编译器隐藏了这些细节，用户在使用对这项技术时候，<strong><span>Handle-Body</span></strong><span> </span>接口成了它唯一的入口。</span></p>
<p>&nbsp;</p>
<p><span>然而</span><strong><span>Handle-Body</span></strong><span>模式也有自己的弱点：</span></p>
<p><span><span>1、</span></span><span>接口类必须把每一个方法调用显示的传递给实现类，这在一个只有一个构造和一个析构的类来说显然不构成负担，但是如果一个庞大的类库，它有上百上千个方法时候，光是编写这些方法传递就有可能非常冗长，这也增加了出错的可能性。</span></p>
<p><span><span>2、</span></span><span>对于关注于性能的应用每一个方法都得有两层的函数调用，嵌套的开销也不理想</span></p>
<p><span><span>3、</span></span><span>由于句柄的存在，依然存在编译连接器兼容性问题。</span></p>
<p>&nbsp;</p>
<p><strong><span><span>1.1.2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>抽象接口</span></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>使用了&#8220;接口与实现的分离&#8221;技术的</span><span> <strong><span>Handle-Body </span></strong></span><span>解决了编译器</span><span>/</span><span>链接器的大部分问题，而</span><span>C++</span><span>面向对象编程中的抽象接口同样是运用了&#8220;接口与实现分离&#8221;的思想，而采用抽象接口对于解决这类问题是一个极其完美的解决方案。</span></p>
<p><span><span>1、</span></span><span>抽象接口的语言描述：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>class IMyString</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Length() const = 0;&nbsp;//</span><span>这表示是一个纯虚函数，具有纯虚函数的接口</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Index(const char *psz) const = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p>&nbsp;</p>
<p><span><span>2、</span></span><span>抽象接口的内存结构：</span></p>
<p><span></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 抽象接口采用虚函数表来调用成员方法。&nbsp;</p>
<p><span><span>3、</span></span><span><span>&nbsp;&nbsp; </span></span><span>抽象接口的实现代码：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>接口：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span><span>class IMyString</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Length() const = 0;&nbsp;//</span><span>这表示是一个纯虚函数，具有纯虚函数的接口</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Index(const char *psz) const = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
</span></span>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>实现：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>class CMyString</span><span>：</span><span>public IMyString</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>private:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;const int m_cch;</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char *m_psz;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CMyString(const char *psz);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual ~CMyString();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int Length() const;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int Index(const char *psz) const;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>从上面采用抽象接口的实例来看，抽象接口解决了</span><span>Handle-Body</span><span>所遗留下来的全部缺陷。</span></p>
<p><span>抽象接口的一个典型应用：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>抽象工厂（</span><span>AbstractFactroy</span><span>）</span></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span><span>1.2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>多继承与菱形缺陷、<span>this</span>跳转等</span></strong></p>
<p><span>多重继承是<span>C++</span>语言独有的继承方式，其它几乎所有语言都秉承了单一继承的思想。这是因为多重继承致命的缺陷导致的：</span></p>
<p><strong><span><span>1.2.1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>菱形缺陷</span></strong></p>
<p><span>当继承基类时，在派生类中就获得了基类所有的数据成员副本。假如类<span>B </span>从<span>A1</span>和<span>A2</span>两个类多重继承而来，这样<span>B</span>类就包含<span>A1</span>、<span>A2</span>类的数据成员副本。</span></p>
<p><span></span><span>考虑如果<span>A1</span>、<span>A2</span>都从某基类派生，该基类称为<span>Base</span>，现在继承关系将出现</span><span>菱形继承关系。<br></span></p>
<p><span>
<div align=center src_cetemp="/images/cppblog_com/andxie99/diamondBug.JPG"><img src="http://www.cppblog.com/images/cppblog_com/andxie99/diamondBug.JPG" border=0></div>
<br>我们<span>C++</span>语言来描述这种继承关系：</span>
<p>&#160;</p>
<p><span>class Base{</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p><span>class A1 :public Base {</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p><span>class A2 :public Base {</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p><span>class B :public A1,public A2 {</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p>&nbsp;</p>
<p><span>那么<span>A1</span>、<span>A2</span>都具有<span>Base</span>的副本。这样<span>B</span>就包含了<span>Base</span>的两个副本，副本发生了重叠，不但增加了存储空间，同时也引入了二义性。这就是菱形缺陷，菱形缺陷的两个缺陷：</span></p>
<p><span><span>1、</span></span><span>子对象重叠</span></p>
<p><span><span>2、</span></span><span>向上映射的二义性。</span></p>
<p><span>菱形缺陷的其中一种解决办法是使用虚拟继承。</span></p>
<p>&nbsp;</p>
<p><span>在<span>C++</span>世界里最广泛的使用虚拟继承解决菱形缺陷的应用便是标准<span>C++</span>的输入<span>/</span>输出<span>iostream</span>；</span></p>
<p>
<div align=center src_cetemp="/images/cppblog_com/andxie99/diamondBug01.JPG"><img src="http://www.cppblog.com/images/cppblog_com/andxie99/diamondBug01.JPG" border=0></div>
<strong><span></span></strong>
<p>&#160;</p>
<p><span></span>&nbsp;</p>
<p><strong>&nbsp;</strong></p>
<p><strong><span><span>1.2.2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>多重接口与方法名冲突问题（</span><span>Siamese twins</span></strong><strong><span>）</span></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>对继承而来的虚函数改写很容易，但是如果是在改写一个&#8220;在两个基类都有相同原型&#8221;的虚函数情况就不那么容易了。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span>提出问题：</span></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>假设汽车最大速度的接口为</span><span>ICar</span><span>，潜艇最大速度的接口为</span><span> IBoat</span><span>，有一个两栖类的交通工具它可以奔跑在马路上，也可以航行在大海中，那么它就同时拥有</span><span>ICar</span><span>、</span><span>IBoat</span><span>两种交通工具的最大速度特性，我们定义它的接口为</span><span>ICarBoat</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class&nbsp;ICar</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span><span>= 0</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class&nbsp;IBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span><span>= 0</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp; </span></span><span>我们先对</span><span>ICarBoat</span><span>的接口做一个尝试：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class CCarBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）；</span><span>//</span><span>既完成</span><span>ICar</span><span>的</span><span>GetMaxSpeed</span><span>（）接口方法又</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span>完成</span><span>IBoat</span><span>的接口方法？显然不能够</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>};</span></p>
<p><strong><span>解决问题：</span></strong></p>
<p><strong><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></strong><span>显然上面这个尝试根本就无法成功，只用一个实现方法，怎么能够求出这个</span><span>ICarBoat</span><span>交通工具奔跑在马路上的最高时速，同时也能够求出航行在大海上的最大航行速度呢。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>上面这一问题矛盾就在一一个方法，却需要两个答案。看来</span><span>ICarBoat</span><span>要返回两个答案就必须有两个方法了，我们假设一个方法是求在陆地上奔跑的速度，名称为</span><span>GetCarMaxSpeed</span><span>（）；另一个方法是求在大海上航行的最大速度，名称为</span><span>GetBoatMaxSpeed</span><span>（）；那这两个方法又怎么和</span><span>GetMaxSpeed</span><span>（）接口方法联系起来呢；</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>幸运的是，我们找到了解决办法，而且解决办法有很多种，下面介绍一下继承法。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class IXCar :public ICar</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>GetCarMaxSpeed();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetCarMaxSpeed</span><span>（）</span><span> = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class IXBoat:public IBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>GetBoatMaxSpeed();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetBoatMaxSpeed</span><span>（）</span><span> = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>classCCarBoat: public IXCar , public IXBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetCarMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230; &#8230;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetBoatMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230; &#8230;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<div align=center src_cetemp="/images/cppblog_com/andxie99/MultiInherit.JPG"><img src="http://www.cppblog.com/images/cppblog_com/andxie99/MultiInherit.JPG" border=0></div>
</span></span>
<p>&#160;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><strong><span><span>1.2.3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>this</span></strong><strong><span>跳转</span></strong></p>
<p><span>this</span><span>跳转是指的&#8220;对象同一性&#8221;问题。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在单一继承的世界内，无论继承关系怎么复杂，针对于同一对象，无论它的子类或者父类的<span>this</span>指针永远相等。即如果</span><span><span> </span></span><span>B</span><span>从</span><span>A</span><span>继承，</span><span>那么 对于一个已经实例化<span>B</span>类的对象 <span>bObject</span>，永远有（<span>B*</span>）<span>&amp;bObject ==(A*)&amp;bObject </span>成立。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>但是在多继承的世界内，上面的等式就不能恒成立，对象的同一性受到了挑战。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>特别的是，在多继承世界内如果菱形关系存在情况下，如果对于已经实例化<span>B</span>类的对象<span>bObject; </span>（<span>Base*</span>）（<span>A1*</span>）<span>&amp;bObject != </span>（<span>Base*</span>）（<span>A2*</span>）<span>&amp;bObject </span>成立，当这种事情发生的时候我们就只能特殊处理了。这种情况在<span>COM</span>应用中处处都会发生。</span></p>
<p>&nbsp;</p>
<p><strong><span><span>1.3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>C++</span></strong><strong><span>多态的两种多态形式和区别</span></strong></p>
<p><strong><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></strong><span>C++</span><span>有两种多态多态形式：</span></p>
<p><span><span>1、</span></span><span>编译时刻多态，编译时刻多态依靠函数重载或者模板实现</span></p>
<p><span><span>2、</span></span><span>运行时刻多态。运行时刻多态依靠需函数虚接口实现</span></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/28494.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-07-21 16:18 <a href="http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的底层机制</title><link>http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 24 Jun 2007 12:43:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26855.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26855.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26855.html</trackback:ping><description><![CDATA[<p>　　c++为我们所提供的各种存取控制仅仅是在编译阶段给我们的限制，也就是说是编译器确保了你在完成任务之前的正确行为，如果你的行为不正确，那么你休想构造出任何可执行程序来。</p>
<p>　　但如果真正到了产生可执行代码阶段，无论是c，c++,还是pascal，大家都一样，你认为c和c++编译器产生的机器代码会有所不同吗，你认为c++产生的机器代码会有访问限制吗？那么你错了。什么const，private，统统没有(const变量或许会放入只读数据段)，它不会再给你任何的限制，你可以利用一切内存修改工具或者是自己写一个程序对某一进程空间的某一变量进行修改，不管它在你的印象中是 private，还是public，对于此时的你来说都一样，想怎样便怎样。</p>
<p>　　另外，你也不要为c++所提供的什么晚期捆绑等机制大呼神奇，它也仅仅是在所产生的代码中多加了几条而已，它远没有你想象的那么智能，所有的工作都是编译器帮你完成，真正到了执行的时候，计算机会完全按照编译器产生的代码一丝不苟的执行。</p>
<p>　　(以下的反汇编代码均来自visial c++ 7.0)</p>
<p>　　一.让我们从变量开始-----并非你想象的那么简单</p>
<p>　　变量是什么，变量就是一个在程序执行过程中可以改变的量。换一个角度，变量是一块内存区域的名字，它就代表这块内存区域，当我们对变量进行修改的时候，会引起内存区域中内容的改变。但是你若是学习过汇编或是计算机组成原理，那么你就会清楚对于一块内存区域来说，根本就不存在什么名字，它所仅有的标志就是他的地址，因此我们若想修改一块内存区域的内容，只有知道他的地址方能实现。看来所谓的变量一说只不过是编译器给我们进行的一种抽象，让我们不必去了解更多的细节，降低我们的思维跨度而已。例如下面这条语句：</p>
<p>　　int a=10;</p>
<p>　　按照我们的思维习惯来讲，就是&#8220;存在一个变量a，它的值是10&#8221;，一切都显得那么的自然。我们不必去在乎什么所谓的地址以及其他的一些细节。然而在这条语句的底层实现中，a已经不能算是一个变量了，它仅仅是一个标记，代表一个地址的标记：</p>
<p>　　mov dword ptr[a],0Ah;</p>
<p>　　怎么样，这条语句不像上面那条易于接受吧，因为它需要了解更多的细节，你几乎不能得到编译器的任何帮助，一切思维上的跨越必须由你自己完成。这条语句应该解释为&#8220;把10写入以a为地址的内存区域&#8221;。你说什么？a有些像指针？对，的确像，但还不是，只不过他们的过程似乎是类似的。这里所说的跨越实际上就是从一个现实问题到具体地址以及内存区域的跨越。</p>
<p>　　二.引用：你可以拥有引用，但编译器仅拥有指针(地址)</p>
<p>　　看过了第一条，你一定对编译器的工作有了一定的了解，实际上编译器就是程序员与底层之间的一个转换层，它把一个高级语言代码转换为低级语言代码，一个编译器完成的转换跨度越大，那么它也就会越复杂，因为程序员的工作都由他代为完成了。C++编译器必然比汇编编译器复杂就是这个道理。如果我问你引用和指针是一样的吗？你或许会说当然不一样了，指针容易产生不安全的因素，引用却不会，真的不会吗？我们来看下面这段代码：</p>
<p>　　int *e=new int(10);</p>
<p>　　int &amp;f=*e;</p>
<p>　　delete e;</p>
<p>　　f=30;</p>
<p>　　你认为上面这段代码怎么样，我感觉就不很安全，它和指针有相同的隐患。因为它所引用的内存区域就不合法。</p>
<p>　　我个人认为，所谓的引用其实就是一种指针，只不过二者的接口并不相同，引用的接口有一定的限制。指针可以一对多，而引用却只能一对一，即&amp;refer不能被改变，但却并不能说一对一就是安全的，只不过危险的系数降低罢了。引用比指针更容易控制。</p>
<p>　　Ok, 下面来说说指针，曾经有过汇编经验的人一定会说，恩，指针的某些地方有些像汇编，尤其是那个&#8220;*&#8221;，怎么就那么像汇编中的&#8220;[]&#8221;啊。的确，它也涵盖了一个寻址的过程。看来指针的确是个比较低级的东西。然而引用却并不那么直接，虽然程序员用起来方便安全了许多。但是你要清楚，只有你可以拥有引用，编译器可没有这个工具，计算机并不认识这个东西。因此，它的底层机制实际上是和指针一样的。不要相信只有一块内存拷贝，不要认为引用可以为你节省一个指针的空间，因为这一切不会发生，编译器还是会把引用解释为指针。不管你相不相信，请看下面这段代码：</p>
<p>　　int&amp; b=a;</p>
<p>　　lea eax,[a];</p>
<p>　　mov dword ptr[b],eax;把a的地址赋给地址为b的一块内存</p>
<p>　　b=50;</p>
<p>　　mov eax,dword ptr[b];</p>
<p>　　mov dword ptr[eax],32h;</p>
<p>　　int *d=&amp;a;</p>
<p>　　lea eax,[a];</p>
<p>　　mov dword ptr[d],eax</p>
<p>　　*d=60;</p>
<p>　　mov eax,dword ptr[d]</p>
<p>　　mov dword ptr[eax],3ch;</p>
<p>　　以上的代码均来自具体的编译器，怎么样，相信了吧，好，让我再来做一个或许不怎么恰当的比拟，你一定编过有关线性表和栈的程序吧，线性表是一个非常灵活的数据结构，在他上面有许多的操作，然而栈呢，它是一个限制性操作的线性表，它的底层操作实际上是由线性表操作实现的。就好比stack与vector的关系，因此指针和引用的关系就好比线性表和栈的关系，引用也就是受限的指针，它对外的接口和指针虽然并不一样，但底层是相同的。</p>
<p>　　下面再来看看引用的一个重要用途，作为函数的参数传递的时候是怎样的情形：</p>
<p>　　void swapr(int &amp;a, int &amp;b)；</p>
<p>　　void swapr(int* a, int *b)；</p>
<p>　　int a=10;</p>
<p>　　int b=20;</p>
<p>　　swapr(a, b);</p>
<p>　　lea eax,[a];</p>
<p>　　push eax; //把a的地址压入堆栈</p>
<p>　　lea ecx,[b];</p>
<p>　　push ecx;</p>
<p>　　call swapr;</p>
<p>　　swapr(&amp;a, &amp;b);</p>
<p>　　lea eax,[a];</p>
<p>　　push eax;</p>
<p>　　lea ecx,[b];</p>
<p>　　push ecx;</p>
<p>　　call swapr;</p>
<p>　　怎么样，用引用和指针传递参数无论是在效率上还是在空间上都是完全一样的，如果妄想不传入地址就修改实参的值，简直就是天方夜谭，这就说明引用的本质就是指针。毕竟它们的行为都太相似了，如果不是这样，你还有什么方法去实现引用吗？记住，引用只不过是编译器为你提供的一个有用且安全的工具，对于机器代码可无法表示它，它把指针一对多的缺点去除，禁止了你的不安全的操作。但回到问题的本源，他们没有任何区别。 </p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-24 20:43 <a href="http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再读《背影》</title><link>http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 23 Jun 2007 02:12:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26853.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26853.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26853.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 父亲早逝，今年已是第十个年头。上周末父亲节，思念之情无以言表，今天恰巧读到朱自清的《背影》，转载如下：<br><br>
<p align=center><strong><span>背影</span></strong><strong><span>&nbsp;</span></strong><strong><span>朱自清</span></strong><strong></strong></p>
<p><span>我与父亲不相见已二年余了，我最不能忘记的是他的背影。那年冬天，祖母死了，父亲的差使也交卸了，正是祸不单行的日子，我从北京到徐州，打算跟着父亲奔丧回家。到徐州见着父亲，看见满院狼藉的东西，又想起祖母，不禁簌簌地流下眼泪。父亲说，&#8220;事已如此，不必难过，好在天无绝人之路！&#8221;</span></p>
<p><span>回家变卖典质，父亲还了亏空；又借钱办了丧事。这些日子，家中光景很是惨淡，一半为了丧事，一半为了父亲赋闲。丧事完毕，父亲要到南京谋事，我也要回北京念书，我们便同行。</span></p>
<p><span>到南京时，有朋友约去游逛，勾留了一日；第二日上午便须渡江到浦口，下午上车北去。父亲因为事忙，本已说定不送我，叫旅馆里一个熟识的茶房陪我同去。他再三嘱咐茶房，甚是仔细。但他终于不放心，怕茶房不妥帖；颇踌躇了一会。其实我那年已二十岁，北京已来往过两三次，是没有甚么要紧的了。他踌躇了一会，终于决定还是自己送我去。我两三回劝他不必去；他只说，&#8220;不要紧，他们去不好！&#8221;</span></p>
<p><span>我们过了江，进了车站。我买票，他忙着照看行李。行李太多了，得向脚夫行些小费，才可过去。他便又忙着和他们讲价钱。<span>我那时真是聪明过分</span>，总觉他说话不大漂亮，非自己插嘴不可。但他终于讲定了价钱；就送我上车。他给我拣定了靠车门的一张椅子；我将他给我做的紫毛大衣铺好坐位。他嘱我路上小心，夜里警醒些，不要受凉。又嘱托茶房好好照应我。我心里暗笑他的迂；他们只认得钱，托他们直是白托！而且我这样大年纪的人，难道还不能料理自己么？<span>唉，我现在想想，那时真是太聪明了！</span></span></p>
<p><span>我说道，&#8220;爸爸，你走吧。&#8221;他望车外看了看，说，&#8220;我买几个橘子去。你就在此地，不要走动。&#8221;我看那边月台的栅栏外有几个卖东西的等着顾客。走到那边月台，须穿过铁道，须跳下去又爬上去。父亲是一个胖子，走过去自然要费事些。我本来要去的，他不肯，只好让他去。我看见他戴着黑布小帽，穿着黑布大马褂，深青布棉袍，蹒跚地走到铁道边，慢慢探身下去，尚不大难。可是他穿过铁道，要爬上那边月台，就不容易了。他用两手攀着上面，两脚再向上缩；他肥胖的身子向左微倾，显出努力的样子。这时我看见他的背影，我的泪很快地流下来了。我赶紧拭干了泪，怕他看见，也怕别人看见。我再向外看时，他已抱了朱红的橘子望回走了。过铁道时，他先将橘子散放在地上，自己慢慢爬下，再抱起橘子走。到这边时，我赶紧去搀他。他和我走到车上，将橘子一股脑儿放在我的皮大衣上。于是扑扑衣上的泥土，心里很轻松似的，过一会说，&#8220;我走了；到那边来信！&#8221;我望着他走出去。他走了几步，回过头看见我，说，&#8220;进去吧，里边没人。&#8221;<span>等他的背影混入来来往往的人里，再找不着了，我便进来坐下，我的眼泪又来了</span>。</span></p>
<p><span>近几年来，父亲和我都是东奔西走，家中光景是一日不如一日。他少年出外谋生，独力支持，做了许多大事。那知老境却如此颓唐！他触目伤怀，自然情不能自已。情郁于中，自然要发之于外；家庭琐屑便往往触他之怒。他待我渐渐不同往日。但最近两年的不见，他终于忘却我的不好，只是惦记着我，惦记着我的儿子。我北来后，他写了一信给我，信中说道，&#8220;我身体平安，惟膀子疼痛利害，举箸提笔，诸多不便，大约大去之期不远矣<span>。</span>&#8221;我读到此处，在晶莹的泪光中，看见那肥胖的，青布棉袍，黑布马褂的背影。唉！我不知何时再能与他相见！</span></p>
<p align=right><span>&nbsp;１９２５年１０月在北京。</span></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-23 10:12 <a href="http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>This case pointers cannot be used </title><link>http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 16 Jun 2007 12:45:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26452.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26452.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26452.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; References allow the use of expressions involving the usual arithmetic operators for large objects without excessive copying. Pointers cannot be used because it is not possible to redefine the meaning of an operator applied to a pointer.</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-16 20:45 <a href="http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2007最牛X网站收集</title><link>http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 16 Jun 2007 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26433.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26433.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26433.html</trackback:ping><description><![CDATA[<p>50. 经典桌面</p>
<p>这个名叫东子的偏执狂不知花了多少工夫，mydeskcity.com的内容量达到了40G，很多图片都是站长本人在国外搜集后，自己进行加工的作品。<br><a href="http://www.mydeskcity.com/">http://www.mydeskcity.com/</a></p>
<p>49. 画猪头</p>
<p>在指定的对话框里面随便画一个猪头，然后点击"提交"，之后会得到一份关于你的个性的报告。当然大部分都是臭骂你的话，但是在你之前已经有965,541个人乐滋滋地找骂了&#8230;&#8230;<br><a href="http://drawapig.desktopcreatures.com/">http://drawapig.desktopcreatures.com/</a></p>
<p>48. 射精计算器</p>
<p>科学是严谨的，因此有人搞出了这么一个在线计算器：把你每周的次数和每次的大致距离填写进去，会得到你已经射了多少米、死了多少精虫的统计数据。<br><a href="http://strongbad.surrealistic.net/ejaculator.php">http://strongbad.surrealistic.net/ejaculator.php</a></p>
<p>47. 通缉犯</p>
<p>这里是全英国最危险的通缉犯发布榜，到目前为止还没见到一个女性（怎么搞的女同志们？撑起半边天来嘛！）你可以参照这里的照片躲开危险，也可以亲自去捉住在逃犯领取1万英镑的奖金。<br><a href="http://www.mostwanted-uk.org/">http://www.mostwanted-uk.org/</a></p>
<p>46. 粗口集合</p>
<p>为了表达对粗口和暴力精神的崇敬，对因殴打老婆而锒铛入狱的著名艺人Ross Kemp的欣赏和遗憾，他的Fans整了这么一个只有他的头像和他"名言"的网站，相当搞笑，堪称英文粗口经典集合。<br><a href="http://www.rosskemp.co.uk/">http://www.rosskemp.co.uk/</a></p>
<p>45. Google员工<br>中文拼音："妈妈说就算你注册的域名再长GOOGLE都能搜索出来" ,据说这是Google中国的员工注册的...打开看看,的确连到google了<br><a href="http://www.mamashuojiusuannizhucedeyumingzaichanggoogledounengsousuochulai.cn/">http://www.mamashuojiusuannizhucedeyumingzaichanggoogledounengsousuochulai.cn/</a></p>
<p>44. 百度员工</p>
<p>百度不服了...中文拼音："妈妈说就算你注册的域名再长baidu都能搜索出来" ...汗...你们在做什么...<br><a href="http://www.mamashuojiusuannizhucedeyumingzaichangbaidudounengsousuochulai.cn/">http://www.mamashuojiusuannizhucedeyumingzaichangbaidudounengsousuochulai.cn/</a></p>
<p>43. 读趣网<br>读趣网，收集了网友们最关心的好东西。Dotree.com，域名谐音,实在是不错。让人羡慕。<br><a href="http://www.dotree.com/">http://www.dotree.com</a></p>
<p>42. 超级装备</p>
<p>通过巨大的照片，了解当今最牛的跑车。<br><a href="http://www.topgear.com/">http://www.topgear.com/</a></p>
<p>41. 烂番茄</p>
<p>最近各种电影网站如同雨后春笋一般纷纷冒出头来，但是这个始终是最好的一个：这里评选出的是最烂的片子，并用"一般烂、很烂、超级烂"这样的级别给它们分类。参评作品中甚至还包括了一些电视游戏。<br><a href="http://www.rottentomatoes.com/">http://www.rottentomatoes.com/</a></p>
<p>40. 魔术吧</p>
<p>街头魔术联盟（Street Magic union），简称"SMU"。这里由一群魔术爱好者自发组织的团体。为所有热爱魔术的人们提供了窥探和偷技的阵地。<br><a href="http://www.magic8.cn/">http://www.magic8.cn/</a></p>
<p>39. 省钱网</p>
<p>天才的理财网，名气和好评迅速彪升，电视台专门为了它开了一档节目。在这里主持人Martin Lewis手把手教给你从租DVD到缴水费省钱的各种方法。<br><a href="http://www.moneysavingexpert.com/">http://www.moneysavingexpert.com/</a></p>
<p>38. 电影随便看</p>
<p>只要在这里下载一个免费软件，请你精于电脑的同事帮忙装好，全世界的电影就都成为你的囊中之物。无论它们是老片子还是现在正在播放的片子，记住手要快，因为很快会有人过来叫你把它们删掉。<br><a href="http://www.bittorrent.com/">http://www.bittorrent.com/</a></p>
<p>37. 免费电话</p>
<p>走到全世界的任何地方，都可以拨打免费的电话。对！一分钟也不用花，只要你装了Skype的这个软件，同时你也叫你的通话伙伴装上它。把耳麦和电脑接好，开始国际长途电话粥吧！<br><a href="http://www.skype.com/">http://www.skype.com/</a></p>
<p>36. 故事会</p>
<p>变态而又真实的各种故事－－如果不是版面限制，我们将很乐于把它们都登出来。比如"用头盔抵挡海鸥的进攻"、"护士偷看成人录像被开除"，只要是见到"Quirkies"的字样点进去就好。<br><a href="http://www.ananova.com/news">http://www.ananova.com/news</a></p>
<p>35. 坏女孩</p>
<p>海湾战争中，美国女兵Lynndie用手比划成枪的样子，指着伊拉克战犯的"那话儿"，这张照片成为人们永远不能忘记的一幕。这个网站也许是为了"纪念"她，搞了这个"模仿Lynndie"的活动，全世界的人都在作出那个姿势。<br><a href="http://www.badgas.co.uk/">http://www.badgas.co.uk/</a></p>
<p>34. 爆笑电视</p>
<p>如果你已经厌倦了现在的电视节目，不妨到这里下载每周一次Ricky的这档爆笑节目。每周一通过Rodcast开始播出一直持续周五。<br><a href="http://www.guardian.co.uk/rickygervais">http://www.guardian.co.uk/rickygervais</a></p>
<p>33. 肮脏美学</p>
<p>一个相当不错的KB网站，比起它来，大多数号称"天下第一KB网站"的网站都显得志大才疏。<br><a href="http://www.sickarts.com/">http://www.sickarts.com/</a></p>
<p>32. 内衣女人</p>
<p>Soho们的福音：这个内衣网站有着非常优秀的摄影、非常迷人的模特和非常性感的内衣，更重要的是你再也不用面红耳赤地去帮老婆买内衣了。<br><a href="http://www.agentprovocateur.com/">http://www.agentprovocateur.com/</a></p>
<p>31. md主机</p>
<p>什么?MD? -_-!!! 哪个国家的域名哦.(是一个空间提供商，有免费空间，还可以注册 xxx.host.md二级域名...)<br><a href="http://www.host.md/">http://www.host.md</a></p>
<p>30. Prank Mail</p>
<p>"想发匿名骚扰邮件吗？想让你的同事以为自己中了100万吗？"这真是一个邪恶的网站，可以提供各式各样的骚扰服务，好在，大多都是善意的。<br><a href="http://www.sharpmail.co.uk/">http://www.sharpmail.co.uk/</a></p>
<p>29. 交友</p>
<p>你是一个孤独的人？到这个只接受可信朋友注册的网站来看看（而不是随意上QQ上搜一个名为"小甜甜"的90多岁老奶奶）。顺便说一句，帕米拉&#183;安德森也是这里的会员。<br><a href="http://www.friendster.com/">http://www.friendster.com/</a></p>
<p>28. 微软？NO！火狐！</p>
<p>指向firefox,什么世道...<br><a href="http://www.ie7.com/">http://www.ie7.com/</a></p>
<p>27. 伤疤大赛</p>
<p>男人就喜欢显摆自己的伤疤，因此应该找个地方让他们比比看。在这里，有这种嗜好的人可以找到全世界的对手，不过别忘了，你"六岁时从火车上掉下来"留下的伤疤和这里的前十名相比看起来可能只是一个小针眼而已。<br><a href="http://www.scarmageddon.com/">http://www.scarmageddon.com/</a></p>
<p>26. 金色视频</p>
<p>就如同在你的电脑上开通了六万个电视频道一样，你只要点点鼠标就可以观看到各种电视节目，从体育到戏剧。这里有100万小时的剪辑供你免费观看。<br><a href="http://www.blinkx.tv/">http://www.blinkx.tv/</a></p>
<p>25. 疯狂的手指</p>
<p>一个极为简单但是极令人着迷的游戏，就是要看你能在多短时间内打完26个字母，然后把你的成绩转给同事们看，然后看着他们拼命敲键盘。我们的记录？6.4秒。但据说最高记录是在1.001秒内敲完了26个字母，是不是地球人啊，他！<br><a href="http://frenzy.morpheme.co.uk/frenzy/">http://frenzy.morpheme.co.uk/frenzy/</a></p>
<p>24. 眼睛的幻觉</p>
<p>德国某大学的科学家们贡献了这个神奇的眼睛魔术网站，在这里你可以体验"空间频率扭曲"，实际上那只是"你的眼睛背叛了你的心"而已。<br><a href="http://www.michaelbach.de/ot/index.html">http://www.michaelbach.de/ot/index.html</a></p>
<p>23. 全球富人榜</p>
<p>把你的收入水平打进去，看看你在地球的财富排行中数老几。你很有可能会惊奇地发现，确实你是属于高收入人群，同阿布在一起！<br><a href="http://www.globalrichlist.com/">http://www.globalrichlist.com/</a></p>
<p>22. 考拉宝</p>
<p>以为是考拉网的工具站，没想到是个人做的，不知道考拉网会怎么想。<br><a href="http://www.kaolaobao.cn/">http://www.kaolaobao.cn</a></p>
<p>21. 掘宝</p>
<p>据我们所知，掘宝网是世界上第一个严肃认真地购买线索资料进行宝藏发掘的网站。他们悬赏10万英镑寻找一个不知道被埋在什么地方的方盒子&#8230;&#8230;当然，这一切都是个游戏。<br><a href="http://www.perplexcity.com/">http://www.perplexcity.com/</a></p>
<p>20. 抓奖网</p>
<p>收集网上有奖活动的网站，见过的最专一的网站之一，倒是一个休闲的好去处<br><a href="http://www.zhuaj.com/">http://www.zhuaj.com</a></p>
<p>19. 可笑的脸</p>
<p>用吃奶的力气做个鬼脸，然后拍成照片传到网上。结果？结果你得到一个印着你的头像的杯子，而你的脸比杯子把儿弯曲得还厉害。<br><a href="http://www.shakeskin.com/">http://www.shakeskin.com/</a></p>
<p>18. 女尸解剖游戏</p>
<p>脱就一脱到底！可是，想想看，除去外套和蕾丝内衣之后，你还能继续脱掉这个女孩身上的什么吗？如果之前被告之是她的头发、面皮、骨头、肠子&#8230;&#8230;还敢将游戏进行到底吗？说实，变态和恶心的程度算不上高，但要把她身上的零件都拿光，还真够麻烦的。<br><a href="http://www.mmsjoy.com/flash/1180_1.htm">http://www.mmsjoy.com/flash/1180_1.htm</a></p>
<p>17. 跑光啦！</p>
<p>这个网站的引人之处就在于那些酒后出丑的姑娘们的照片。<br><a href="http://www.partyflashers.com/">http://www.partyflashers.com/</a></p>
<p>16. MP3问答</p>
<p>把你最喜欢的乐队名字写进去，然后玩一个10回合的小游戏，把正在播放的歌名正确猜对。<br><a href="http://www.scenta.co.uk/games/whats_that_song.cfm">http://www.scenta.co.uk/games/whats_that_song.cfm</a></p>
<p>15. 射门</p>
<p>一个与众不同的足球游戏：挑选你愿意参加的联赛和队伍，你在游戏中每进一球，都将给自己的联盟加上一分。<br><a href="http://www.playforyourclub.com/">http://www.playforyourclub.com/</a></p>
<p>14. 跳舞的傻瓜</p>
<p>我们猜测，叫每个打开此网页的人都哈哈大笑是站长的目的。上传或者选择一个头像，然后选择一个身体，再然后就让这个小兄弟在你的屏幕上不停地跳舞吧！<br><a href="http://www.muglets.com/">http://www.muglets.com/</a></p>
<p>13. 养盒子</p>
<p>这个游戏有一点点抽象，但是却很好玩：按照符合逻辑的顺序，用不同的道具来建设这个盒子，顺序正确它就会逐步长成为&#8230;&#8230;不知道什么东西，我们的逻辑思维还没那么好。<br><a href="http://www.eyemaze.com/grow/cube/">http://www.eyemaze.com/grow/cube/</a></p>
<p>12. 淘宝贝</p>
<p>在一些男性会为之发疯的好玩具、小物件儿出现在商店里之前，它们极有可能会出现在这里。这里的东西有"第一人称射击单车控制器"还有能够把你的PC、PS2和XBOX连到一起的连接装置&#8230;&#8230;欢迎来到天堂！<br><a href="http://www.engadget.com/">http://www.engadget.com/</a></p>
<p>11. 扑克先生</p>
<p>管理员最热爱的体育项目之一就是扑克牌，因此我们正好知道一个不错的扑克网站。你每天都可以坐在自己的办公桌后面于7万名其他的扑克爱好者们在线拼杀&#8230;&#8230;<br><a href="http://www.partypoker.com/">http://www.partypoker.com/</a></p>
<p>10. 偷拍地球</p>
<p>从一个悬挂在太空、注视着地球的卫星的角度开始，一点点放大，一直看到大北窑的堵车状&#8230;&#8230;有点变态，不过很好玩。有个问题：如果我们都能看到这么多，那么军队的电脑上都能看到什么呢？<br><a href="http://www.flashearth.com/">http://www.flashearth.com/</a></p>
<p>9. 电台天堂</p>
<p>建立你自己的私人电台名称（例如"老陈FM"），输入你喜欢的波段地址，然后就等着从电脑里飘来美妙MP3吧！就像你从Amazon里面购买来的一样！<br><a href="http://www.pandora.com/">http://www.pandora.com/</a></p>
<p>8. 个人空间</p>
<p>有个美国佬最近把50多亿美金都仍在一个网站上，由此我们可以预见到互联网的未来。赶紧找个空间创建你自己的天地，把你的照片、音乐传上去，再搞点小买卖。这里已经有4000万用户，数目相当于丹麦、瑞典、澳大利亚和瑞士的人口总和。<br><a href="http://www.myspace.com/">http://www.myspace.com/</a></p>
<p>7. 飞虎队</p>
<p>网站首页上写着：这里的主要内容是介绍香港pol.ice的特种部队－－"特别任务连"。特务连？不，是飞虎队。虽然站长声称这不是官方网站，但里面大量装备足以让我们飙出鼻血。<br><a href="http://www.sdupro.com/index2.html">http://www.sdupro.com/index2.html</a></p>
<p>6. 照片分享</p>
<p>现在连照片的上传和分享都有软件可以帮你打理完成了：下载这个免费的软件，然后往里面填好你的链接地址，就可以和朋友们分享了。如果你乐意，你甚至可以把它们变成海报、画册、甚至是邮票，当然也可以自由浏览他人的作品。<br><a href="http://www.flickr.com/">http://www.flickr.com/</a></p>
<p>5. 安全隐私</p>
<p>任何人都可以登录这个网站，邮寄一张电子贺卡，吐露心底的秘密或者偷窥别人的秘密。浏览者可以挖掘出人们最悲惨、最滑稽、最古怪、最疯狂的一面。更重要的是这里的秘密最安全。<br><a href="http://postsecret.blogspot.com/">http://postsecret.blogspot.com/</a></p>
<p>4. 秘密的Google</p>
<p>我们没疯：你一直点击"更多"，直到它最终带领你进入一个全新的Google世界。你直到通过Google你可以用一颗卫星看到自己家的房子吗？用6GOOG得到免费的地图、电影放映时间？把"鱼"这个词翻译成意大利语？你不知道，那就来试试吧！<br><a href="http://www.google.com/">http://www.google.com/</a></p>
<p>3. 网络精选</p>
<p>住在伦敦的网络老油条理查德创建了这个网站，上面包含网络上最好的视频剪辑、游戏、姑娘和图片。"我本来的动机是要把邮箱里面每天收到的各种好玩儿的东西集中起来放到网上和朋友们分享。"他说。你在这里泡上整整一个下午，也不一定能真正看完这儿全部宝贝的九牛一毛。<br><a href="http://www.kontraband.com/">http://www.kontraband.com/</a></p>
<p>2. 60X1</p>
<p>被网名传为世界最牛&#215;的网站，它的域名由60个1组成。在首页有一个小小的"ENTER"健，点进去是一幅又一幅漫画，创意一流，无懈可击。我们猜测，这也许是个伊拉克人的作品吧&#8230;&#8230;<br><a href="http://www.111111111111111111111/">http://www.111111111111111111111</a> ... 111111111111111.com (自己输入试试吧)</p>
<p>1. 冠军</p>
<p>我们粗略计算了一下在公司玩那种网上下载的小游戏的时间，结果可以用年来计算。这里的东西就是专门给我们这样喜欢浪费时间的人准备的，无论是第一人称射击游戏还是赛车游戏，基本上全都是免费的。例如"武装直升机3"和"愤怒机甲"，它们就是两个画面十分漂 亮的爽游戏，快和你的职业前途说"再见"吧！<br><a href="http://www.miniclip.com/">http://www.miniclip.com/</a></p>
<p>0. bolm<br>最不牛X的：<a href="http://bolm.cn/">http://bolm.cn</a>&nbsp; --&nbsp; 必看</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-16 11:58 <a href="http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>被误解的C++</title><link>http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Fri, 15 Jun 2007 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26396.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26396.html</trackback:ping><description><![CDATA[<p><br>&nbsp;&nbsp;&nbsp; 从CSDN上读到一篇文章，深有同感，原文如下：<br>&nbsp;&nbsp;&nbsp; 传统上认为，C++相对于目前一些新潮的语言，如Java、C#，优势在于程序的运行性能。这种观念并不完全。如果一个人深信这一点，那么说明他并没有充分了解和理解C++和那个某某语言。同时，持有这种观念的人，通常也是受到了某种误导（罪魁祸首当然就是那些财大气粗的公司）。对于这些公司而言，他们隐藏了C++同某某语言间的核心差别，而把现在多数程序员不太关心的差别，也就是性能，加以强化。因为随着cpu性能的快速提升，性能问题已不为人们所关心。这叫&#8220;李代桃僵&#8221;。很多涉世不深的程序员，也就相信了他们。于是，大公司们的阴谋也就得逞了。<br>&nbsp;&nbsp;&nbsp; 这个文章系列里，我将竭尽所能，利用一些现实的案例，来戳破这种谎言，还世道一个清白。但愿我的努力不会白费。</p>
<p><br>软件工程</p>
<p>&nbsp;&nbsp;&nbsp; 一般认为，使用Java或C#的开发成本比C++低。但是，如果你能够充分分析C++和这些语言的差别，会发现这句话的成立是有条件的。这个条件就是：软件规模和复杂度都比较小。如果不超过3万行有效代码（不包括生成器产生的代码），这句话基本上还能成立。否则，随着代码量和复杂度的增加，C++的优势将会越来越明显。<br>&nbsp;&nbsp;&nbsp; 造成这种差别的就是C++的软件工程性。在Java和C#大谈软件工程的时候，C++实际上已经悄悄地将软件工程性提升到一个前所未有的高度。这一点被多数人忽视，并且被大公司竭力掩盖。<br>&nbsp;&nbsp;&nbsp; 语言在软件工程上的好坏，依赖于语言的抽象能力。从面向过程到面向对象，语言的抽象能力有了一个质的飞跃。但在实践中，人们发现面向对象无法解决所有软件工程中的问题。于是，精英们逐步引入、并拓展泛型编程，解决更高层次的软件工程问题。（实际上，面向对象和泛型编程的起源都可以追溯到1967年，但由于泛型编程更抽象，所以应用远远落后于面向对象）。<br>&nbsp;&nbsp;&nbsp; 一个偶然的机会，我突发奇想，试图将货币强类型化，使得货币类型可以采用普通的算术表达式计算，而无需关心汇率换算的问题。具体的内容我已经写成文章，放在blog里：<a href="http://blog.csdn.net/longshanks/archive/2007/05/30/1631391.aspx">http://blog.csdn.net/longshanks/archive/2007/05/30/1631391.aspx</a>。（CSDN的论坛似乎对大文章有些消化不良）。下面我只是简单地描述一下问题，重点还在探讨语言能力间的差异。<br>&nbsp;&nbsp;&nbsp; 当时我面临的问题是：假设有四种货币：RMB、USD、UKP、JPD。我希望能够这样计算他们：<br>RMB rmb_(1000);<br>USD usd_;<br>UKP ukp_;<br>JPD jpd_(2000);</p>
<p>usd_=rmb_;//赋值操作，隐含了汇率转换。usd_实际值应该是1000/7.68=130.21<br>rmb_=rmb_*2.5;//单价乘上数量。<br>ukp_=usd_*3.7;//单价乘上数量，赋值给英镑。隐含汇率转换。<br>double n=jpd_/(usd_-ukp_);//利用差价计算数量。三种货币参与，隐含汇率转换。<br>而传统上，我们通常用一个double或者currency类型表示所有货币。于是，当不同币种参与运算时，必须进行显式的汇率转换：<br>double rmb_(100), usd_(0), ukp_(0), jpn_(2000);</p>
<p>usd_=rmb_*usd_rmb_rate;<br>ukp_=(usd_*usd_ukp_rate)*3.7;<br>double n=jpd_/((usd_*usd_jpd_rate)-(ukp_*ukp_jpd_rate))<br>很显然，强类型化后，代码简洁的多。并且可以利用重载或特化，直接给出与货币相关的辅助信息，如货币符号等（这点我没有做，但加上也不复杂）。<br>在C++中，我利用模板、操作符重载，以及操作符函数模板等技术，很快开发出这个货币体系：<br>template&lt;int CurrType&gt;<br>class Currency<br>{<br>public:<br>&nbsp;&nbsp; Currency&lt;CurrType&gt;&amp; operator=(count Currency&lt;ct2&gt;&amp; v) {<br>&#8230;<br>&nbsp;&nbsp; }<br>public:<br>&nbsp;&nbsp; double _val;<br>&#8230;<br>};<br>template&lt;int ty, int tp&gt;<br>inline bool operator==(currency&lt;ty&gt;&amp; c1, const currency&lt;tp&gt;&amp; c2) {<br>&#8230;<br>}<br>&nbsp;<br>template&lt;int ty, int tp&gt;<br>inline currency&lt;ty&gt;&amp; operator+=(currency&lt;ty&gt;&amp; c1, const currency&lt;tp&gt;&amp; c2) {<br>&#8230;<br>}<br>template&lt;int ty, int tp&gt;<br>inline currency&lt;ty&gt; operator+(currency&lt;ty&gt;&amp; c1, const currency&lt;tp&gt;&amp; c2) {<br>&#8230;<br>}<br>&#8230;<br>总共不超过200行代码。（当然，一个工业强度的货币体系，需要更多的辅助类、函数等等。但基本上不会超过500行代码）。如果我需要一种货币，就先为其指定一个int类型的常量值，然后typedef一下即可：<br>const int CT_RMB=0;//也可以用enum<br>typedef Currency&lt;CT_RMB&gt;RMB;<br>const int CT_USD=1;<br>typedef Currency&lt;CT_USD&gt;USD;<br>const int CT_UKP=2;<br>typedef Currency&lt;CT_USD&gt;USD;<br>const int CT_JPD=3;<br>typedef Currency&lt;CT_USD&gt;USD;<br>&#8230;<br>每新增一种货币，只需定义一个值，然后typedef即可。而对于核心的Currency&lt;&gt;和操作符重载，无需做丁点改动。<br>之后，我试图将这个货币体系的代码移植到C#中去。根据试验的结果，我也写了一篇文章（也放在blog里：<a href="http://blog.csdn.net/longshanks/archive/2007/05/30/1631476.aspx">http://blog.csdn.net/longshanks/archive/2007/05/30/1631476.aspx</a>）。我和一个同事（他是使用C#开发的，对其更熟悉），用了大半个上午，终于完成了这项工作。<br>令人丧气的事，上来就碰了个钉子：C#不支持=的重载。于是只能用asign&lt;&gt;()泛型函数代替。之后，由于C#的泛型不支持非类型泛型参数，即上面C++代码中的int CurrType模板参数的泛型对等物，以及C#不支持泛型操作符重载，整个货币系统从泛型编程模式退化成了面向对象模式。当然，在我们坚持不懈的努力下，最后终于实现了和C++中一样的代码效果（除了那个赋值操作）：<br>assign(rmb_, ukp_);<br>assign(usd_, rmb_*3.7);<br>&#8230;<br>我知道，有些人会说，既然OOP可以做到，何必用GP呢？GP太复杂了。这里，我已经为这些人准备了一组统计数据：在C#代码中，我实现了3个货币，结果定义了4个类（一个基类，三个货币类）；重载30个算术操作符（和C++一样，实现10个操作符，每个类都得把10个操作符重载一遍）；6个类型转换操作符（从两种货币类到第三货币类的转换操作符）。<br>这还不是最糟的。当我增加一个货币，货币数变成4个后，数据变成了：5个类；40个算术操作符重载；12个类型转换操作符重载。<br>当货币数增加到10个后：11个类；100个算术操作符重载；90个类型转换操作符重载。<br>反观C++的实现，3个货币时：1个类模板；1个赋值操作符重载模板；10个算术操作符重载模板；外加3个const int定义，3个typedef。<br>10个货币时：1个类模板；1个赋值操作符重载模板；10个算术操作符重载模板；const int定义和typedef分别增加到10个。<br>也就是说C++版本的代码随着货币的增加，仅线性增加。而且代码行增加的系数仅是2。请注意，是代码行！不是类、函数，也不是操作符的数量。而C#版本的代码量则会以几何级数增加。几何级数！！！<br>这些数字的含义，我就不用多说了吧。无论是代码的数量、可维护性、可扩展性C++都远远好于C#版本。更不用说可用性了（那个assign函数用起来有多难看）。<br>&nbsp;&nbsp;&nbsp; 我知道，有些人还会说：货币太特殊了，在实践中这种情况毕竟少见。没错，货币是比较特殊，但是并没有特殊到独此一家的程度。我曾经做了一个读取脚本中的图形信息，并绘图输出的简单案例，以展示OOP的一些基本概念，用于培训。但如果将其细化，可以开发出一个很不错的脚本绘图引擎。其中，我使用了组合递归、多态和动态链接，以及类工厂等技术。就是那个类工厂，由于我使用了模板，使得类工厂部分的代码减少了2/3，而且没有重复代码，更易维护。关于抽象类工厂的GP优化，Alexandrescu在其《Modren C++ design》中，有更多的案例。同样的技术，还可以推广到业务模型的类系统中，优化类工厂的代码。<br>如果还不满意，那么就去看看boost。boost的很多库实现了几乎不可想象的功能，比如lambda表达式、BGL的命名参数等等。它为我们很多优化软件代码新思路，很多技术和方法可以促进我们大幅优化代码，降低开发成本。<br>&nbsp;&nbsp;&nbsp; 最后，如果你认为C#的最大的优势在于.net平台，那我可以告诉你，这个世界上还有一种东西叫C++/CLI，完全可以满足.net的开发，而且更好，足以擦干净.net那肮脏的屁股。不过，这将会是另外一个故事了&#8230;<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-15 20:41 <a href="http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于系统进程的一点很基础的知识</title><link>http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 09 Jun 2007 07:36:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/25900.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/25900.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/25900.html</trackback:ping><description><![CDATA[<br>&nbsp;&nbsp;&nbsp; 系统进程<br>&nbsp;&nbsp;&nbsp; Windows NT/2000操作系统拥有少量的系统进程来管理登录、服务、用户进程。你能通过任务管理器列出系统进程或者通过Platform SDK的任务列表工具（tlist）来找到他们。<br>&nbsp;&nbsp;&nbsp; 当Windows NT/2000操作系统运行时，可以将进程大致分成三个层次：<br>&nbsp;&nbsp;&nbsp; 第一层就包含一个系统进程——系统闲逛进程，该进程的ID为0；<br>&nbsp;&nbsp;&nbsp; 第二层包含所有其他系统进程，这些进程开始于一个称为system的进程，该进程是session manager process(smss.exe)的父进程，session manager process 是Win32 subsystem process(csrss.exe)和logon process(winlogon.exe)的父进程；<br>&nbsp;&nbsp;&nbsp; 第三层开始于一个程序管理进程（explorer.exe），它是所有用户进程的父进程。
<img src ="http://www.cppblog.com/andxie99/aggbug/25900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-09 15:36 <a href="http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一道面试题</title><link>http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 03 Jun 2007 10:27:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/25393.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/25393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/25393.html</trackback:ping><description><![CDATA[<br>&nbsp;&nbsp;&nbsp; 这道题不是很难，但面试的时候一定要冷静，其实很多事情只要找到突破口，问题就迎刃而解了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A B C D E<br>&nbsp;&nbsp;&nbsp; &#215;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br>&nbsp;&nbsp;&nbsp; --------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E D&nbsp;C&nbsp;B A<br>&nbsp;&nbsp;&nbsp; A、B、C、D、E分别代表一位不同的数字，求 A、B、C、D、E。 
<img src ="http://www.cppblog.com/andxie99/aggbug/25393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-03 18:27 <a href="http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个简单的不依靠MFC的面向对象的Windows程序</title><link>http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 02 Jun 2007 04:36:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/25315.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/25315.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/25315.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 闲时顺手翻了翻《Windows Graphics Programming》，发现里面的示例代码很不错，对设计应用程序框架和理解现有的应用程序框架很有帮助（尤其是MFC）。先来看一个很简单的用面向对象的思想包装API函数的KWindow类。示例代码贴出来，申明一下，代码不是我写的，但有可能做一些改动，加了很多罗嗦的注释，只是想节约以后阅读的时间。&nbsp;&n...&nbsp;&nbsp;<a href='http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html'>阅读全文</a><img src ="http://www.cppblog.com/andxie99/aggbug/25315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-02 12:36 <a href="http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员创业</title><link>http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Fri, 04 May 2007 14:43:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/23419.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/23419.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/23419.html</trackback:ping><description><![CDATA[<p><br>&nbsp;&nbsp;&nbsp; 当人们还在浩叹第一次网络泡沫破灭的时候，互联网已经悄悄迎来了它的第二个春天；从某种意义上看，甚至已经进入了夏天——热烈但不乏浮躁、兴奋但失之肤浅。某位投资人声称今年总共有三十亿美金资本进入中国，言下之意，大家都可以甩开膀子大干快上，登陆纳市不好说，搞笔钱进来花差花差多半是没问题的。</p>
<p>&nbsp;&nbsp;&nbsp; 另一方面，程序员创业，在中国乃至国外，都不是什么新鲜事儿。我们是那么一群聪明、优秀的家伙，大脑发达，点子就像啤酒的泡沫，扑腾扑腾直往外冒，天生我才，有什么做不到的呢？遥想比尔盖茨当年，西装革履，谈笑间，多少豪杰灰飞烟灭&#8230;&#8230;</p>
<p>&nbsp;&nbsp;&nbsp; 于是我看到，无数公司成立了，眼看他雄心勃勃，眼看他一败涂地。成败固然不足以论英雄，然而英雄却不得不面对可能的成败。可惜的是，程序员朋友们在创业的时候，往往没有做好充分准备。据一些资料显示，百分之七十五的新创公司，会在两、三年内倒闭。笔者也曾经见过许多程序员创业失败的个案；成功或不成功，有很多因素制约；对于立志创业的程序员，至少应该突破三关。</p>
<p>&nbsp;&nbsp;&nbsp; 第一是模式关。你的创业计划，也许起源于灵机一动。可惜的是，好点子并不能保证你创业成功。我相信多数程序员的点子，尚不至于低级到靠软色情、盗版、恶性SEO等等下作手段去骗取广告费的地步，但怎么从点子变成盈利模式，却是让很多创业者迷惑的事情。在一些业界聚会上，总听到类似&#8220;只要有流量，总有办法赚钱&#8221;之类的说法，在2000年持同样言论的创业者，多数已经成为失败的先烈，因为他们始终没明白，赚现钱的生意才是好生意。三大门户成功的要点，在于他们想出办法，把流量转化为盈利模式。缺乏有效的模式，流量只是成本。确定有效经营模式、组建有力创业团队，是首要任务。</p>
<p>&nbsp;&nbsp;&nbsp; 第二是管理关。从程序员变成管理者，是艰难的过程。你得明白两件事：一、管理和写程序一样，是门科学；二、人和计算机不一样，人有感情、会出错。协调沟通能力，是程序员创业必备的素质。曾经眼见一些项目经理，和手下技术人员通过邮件争辩不休，甚至发展到在Blog上互相嘲讽，这样的管理，可谓彻底失败。另一个极端是，和手下称兄道弟、一团和气，工作被感情所左右，酒肉害了朋友。管理有那么难吗？我看未必。只做对公司有利的事，就是根本原则。在和你的手下打交道时，请三思：我这么做，对公司有好处吗？对事业有好处吗？如果答案是否定的，那你需要另一个解决方案。</p>
<p>&nbsp;&nbsp;&nbsp; 第三是坚持关。一位多次创业不成功的朋友告诉我，他总结了一条&#8220;三年定律&#8221;，即任何事如果不能坚持三年，则一定失败。诚哉斯言！另一位朋友说，中国人相信机会，西方人相信方向和时间，虽有些偏激，却也不乏道理。许多程序员都属于思维活跃、点子特多的一类人，当有新鲜的想法出来时，他们倾向于放弃或冷落手上正在执行的计划。点子复点子，点子何其多，每天新点子，万事成蹉跎。西谚有云，双鸟在林不如一鸟在手；吃到嘴里的鸭子才是好鸭子，湖里那只鸭子看起来比较肥？也许吧，不过，吃了这只鸭子再去涉水抓那只，是不是更有把握呢？</p>
<p>&nbsp;&nbsp;&nbsp; 文短意深，未尽之处不及一一道来。奉上忠言数句，与程序员朋友们共勉：你永远不是最聪明的人；手下比你强是好事；创业不怕起步晚，只怕起个不停。<br>&nbsp;<br><br>&nbsp;原文地址：<a href="http://blog.csdn.net/ljah/archive/2007/05/04/1596366.aspx">http://blog.csdn.net/ljah/archive/2007/05/04/1596366.aspx</a></p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/23419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-05-04 22:43 <a href="http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是高级C++？</title><link>http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 22 Apr 2007 11:50:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/22600.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/22600.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/22600.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 整理资料时，发现了《什么是高级C++》这个ppt。这是一个C++发展方向的介绍，个人觉得很不错，把内容贴了出来，同是也可以<a href="http://www.cppblog.com/Files/andxie99/《什么是高级C++》.rar">点击下载</a>。<br><br></p>
<p align=center><strong>什么是高级C++？</strong></p>
<p align=center>——软件工业化时代的C++价值观<br>孟岩<br>《程序员》杂志社</p>
<p><br><strong>开门见山</strong></p>
<p>主要论点：<br>&nbsp;&nbsp;&nbsp; 1. C++本质上是一种重&#8220;创新&#8221;而轻&#8220;生产&#8221;的语言，到目前为止仍然是主流语言中最适合技术创新的一个；<br>&nbsp;&nbsp;&nbsp; 2. 1995年之前，整个软件产业处于&#8220;创新为王&#8221;的阶段，C++是最适合这个阶段的语言，这是C++红极一时的大背景和根本原因。<br>&nbsp;&nbsp;&nbsp; 3. 1995年发生了一系列影响深远的事件，软件产业整体上转向工业化，为了支持工业化，创新的重点由技术创新转向体系创新。然而C++没有能够迅速适应这一变化。<br>&nbsp;&nbsp;&nbsp; 4. 今天，C++应当准确定位，弥补不足，有针对性地发展，它将仍然是最重要的几种工业级语言之一。</p>
<p><br><strong>从一本书说起</strong><br>James Coplien，Advanced C++ Programming Styles and Idioms, Addison Wesley, 1991<br>—— 市面上唯一一本名副其实的&#8220;高级&#8221;C++书（Scott Meyers）<br>&nbsp;●面向对象特性的运用和把握<br>&nbsp;●面向对象的程序风格<br>&nbsp;●动态特征的运用和超越<br>&nbsp;●符号语言模拟<br>&nbsp;●设计模式</p>
<p>&nbsp;&nbsp;&nbsp; 这本书代表了当时专家们对于&#8220;高级C++&#8221;的理解，换句话说代表了当时C++社群的一个审美价值取向。我们看到了什么？技术、技巧、风格、模式，但没有与工程相关的东西。更有意思的事情是，这本书的中文版12年后被剽窃出版，此时书中对于C++面向对象能力发挥到了我当时没有想到的程度。这说明即使在template被广泛应用之前，C++语言的技巧性就达到了如此的高度。然而耐人寻味的是，书中最高深的技巧从来就没有在C++实践中流行过。</p>
<p><strong>另一本书...</strong><br>Scott Meyers, Effective C++ ，1991年第1版，1998年第二版，2005年第三版。<br>&nbsp;●来自教学经验<br>&nbsp;●最初想开发一个代码扫描工具<br>&nbsp;●包含实际工程建议<br>&nbsp;●历史上最重要的C++著作之一</p>
<p>&nbsp;&nbsp;&nbsp; 这本书出版的同时，还有一本在C++历史上影响更大的书问世——Scott Meyers的Effective C++。这本书并没有过多地探索语言技巧，而是探讨实践中应当遵循的规则，或者换句话说，探讨怎样在应用这种语言的同时保持软件的质量，提高开发效率。这本书的内容被整个C++社群熟知并吸收，至今仍在翻新，影响着更多的人。</p>
<p><strong>还是在1991年...</strong><br>&nbsp;●&#8220;按照1991年3月C++程序员增长的速度计算，到1996年5月，全世界每一个人都将成为C++程序员。此后我们将不得不教外星人学习C++。&#8221;<br>&nbsp;●问题：当时人们为什么如此疯狂地学习一种新语言？<br>&nbsp;&nbsp;&nbsp; 答案很有趣：大部分人是盲从。但他们所追随的人并非等闲之辈，几乎所有在AT&amp;T Bell Labs、Sun、Borland、IBM、Microsoft的C语言大师都转向C++（Brain Kernighan，Jon Bentley，Peter van der Linden）。而这些人转向C++，不是因为他们知道Effective C++，而是因为他们知道Advanced C++。什么意思呢？就是说人们转向C++，是因为C++充满了令人兴奋的新技巧和未知的创新空间。<br></p>
<p><br><strong>1991年...</strong><br>&nbsp;●5000行C代码可以写一个完整的应用程序，获得数万$的回报；<br>&nbsp;●一个TSR式的Help程序可以以shareware的方式通过磁盘发行，开发者银行户头里会收到大量汇款；<br>&nbsp;●John Carmark和Michael Abrash正在各自擅长的方向上不断创新。Doom发行后，id获得收入一度超过微软销售额。</p>
<p><strong>C++历史选择中&#8220;创新&#8221;压倒&#8220;生产&#8221;</strong><br>&#8220;相信程序员&#8221;；<br>Be an enable language;<br>Zero overhead；<br>STL投票的通过；<br>偏特化的引入<br>多继承<br>Generic/Generated/Meta<br>IOStream库的设计<br>Loki/Boost<br><br><span style="COLOR: red">counted_ptr被否决<br>可选GC方案被否决<br>加入类似delegate的对象方法指针提议未引起关注；<br>virtual关键字<br>exception机制<br>缺乏Thread, Network, Regex, DB...等标准库<br>没有ABI规范<br>孱弱的RTTI</span></p>
<p>&nbsp;&nbsp;&nbsp; 并不是事后诸葛亮式的谴责，这就是C++的历史选择，无所谓对错。</p>
<p>&nbsp;&nbsp;&nbsp; C++重创新轻生产，重技巧轻规范，语言上的创新试验直到1996年ANSI C++标准草案落地才结束。直到2001年Modern C++ Design出版，人们还不断地发现新的语言运用技巧。我们每个人都经历过这个阶段，在实践中发现一个问题，想方设法用尽各种语言技巧来克服它，成则欣喜，败不气馁。我们都曾经相信，C++中一切问题都可以优雅地解决，只有想不到，没有做不到。问题是，从Advanced C++到Modern C++ Design，许许多多令人第一眼看上去无比惊喜的技术，最后在实践中被大范围推广运用的少之又少。C++大师们说这是教育问题，真的是这样吗？</p>
<p><strong>C++社群的价值观</strong><br>&nbsp;●用优雅的技巧解决复杂问题<br>&nbsp;●自己动手，丰衣足食<br>&nbsp;●决不让运行时效率蒙受半点损失<br>&nbsp;●妙者为王<br>&nbsp;&nbsp;&nbsp; &#8220;管理一群C++程序员就像放牧一群骄傲的猫。&#8221;——B. Moo<br>&nbsp;&nbsp;&nbsp; &#8220;C++程序员是高速公路上穿着短皮茄克，带着墨镜，抽着雪茄，挥舞着铁链的英勇无畏的摩托骑士。&#8221; ——VC产品经理</p>
<p><strong>1995年：转折点<br></strong>&nbsp;●Windows 95问世：GUI时代、保护模式操作系统时代、多线程时代的到来，是推动软硬件规模迅速膨胀；<br>&nbsp;●Netscape Navigator vs. Internet Explorer: Web的兴起将人类一下子拖入互联网时代, 个人与企业应用软件网络化；<br>&nbsp;●Java诞生：提供了网络时代、跨平台时代优于C++的企业应用软件开发语言；<br>&nbsp;●COM时代到来<br>&nbsp;●Delphi诞生：创新与工程原则平衡的典范；</p>
<p><br><strong>1995年：C++全盛时代</strong><br>&nbsp;●C++标准草案接近完成，语言基本稳定；<br>&nbsp;●C++工具大战结束：来自商业竞争的动力消失，MFC获胜；<br>&nbsp;●很多主流软件厂商转向C++，C++开始在大范围内被用于大规模软件开发；<br>&nbsp;●一切迹象表明，软件产业的重点将有创新转向生产。但是：C++社群在指导思想上并没有发生相应的变化。</p>
<p>&nbsp;<br><strong>我们的历史失误</strong><br>&nbsp;●C++社群从来没有联合起来支持任何一个跨平台的二进制组件标准（如COM/SOM/CCM）和基础库（如Apache APR、ACE OS Wrapper）；<br>&nbsp;●C++社群从来没有联合起来支持任何一个跨平台的C++虚拟机、解释器、内存检测工具和错误录像工具，也从来没有促成过一个安全的库；<br>&nbsp;●Boost出现于1999-2000年，而在此之前的跨平台C++库都没有获得广泛的支持；<br>&nbsp;●钟情于用C++语法（无论多么复杂和稀奇古怪）完成所有的任务，却丢掉了老祖宗C语言的看家法宝——Little Language；<br>&nbsp;●对于风格争论不休，对于明显的技术进步拒不接受，对于很多后来被证明并不实用的技巧趋之若鹜。</p>
<p>&nbsp;&nbsp;&nbsp; 没有跨平台的基础库，就没有跨平台的动态模块加载机制；<br>&nbsp;&nbsp;&nbsp; John Spencer夭折的书《The Art of C Programming》，GoF的Interpreter模式；Little Language实际上具有反映计算机本质的一些东西，现在却成了很少为C++程序员所采用和熟悉的工具。</p>
<p>&nbsp;</p>
<p><strong>2005年，C++的现实处境</strong><br>&nbsp;●在系统编程领域仍然强势；<br>&nbsp;●套装软件主流开发语言之一；<br>&nbsp;●嵌入式开发领域进展较快；<br>&nbsp;●游戏引擎开发主力；<br>&nbsp;●科学计算方面略有一席之地<br>&nbsp;●遗留项目的维护；<br>&nbsp;●在企业应用开发领域快速收缩；<br>&nbsp;●Web开发中的影子语言；<br>&nbsp;●从高校主流教学中退潮；<br>&nbsp;●整体水平仍然不高，很多企业急于摆脱；<br>&nbsp;●最致命的：真正了解和熟练掌握C++的人太少；</p>
<p>案例：1. 国外一家公司花高薪聘人，要么能维护目前百万行规模的代码，要么把它转成Java；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. IBM Workplace，项目一开始C++/Java并重，之后C++比重越来越小；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. 微软与中国电信合作一个项目，客户端软件本来要用C++写，后来赶到产品化周期太长，改用C#，后发先至。&nbsp;</p>
<p><br><strong>问题何在<br></strong>&nbsp;●当前的软件产业发展的主要矛盾——各行各业对软件生产标准化、规模化、高质量要求与慢节奏、低效率、低质量的软件开发之间的矛盾。<br>&nbsp;●解决这个矛盾的关键：组件化体系，成熟的软件生产工具和环境，不断的创新精神。<br>&nbsp;●C++在外部环境已经发生根本变化的近十年时间里，没有抓住这个主要矛盾。</p>
<p><br><strong>重新评估我们的C++价值取向</strong><br>&nbsp;&nbsp;&nbsp; 重新评估&#8220;高级C++&#8221;的现实含义：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 简洁有效优于惊世骇俗；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 开放灵活优于保守固执；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 帮助他人优于凸现自己；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 领域创新优于卖弄技巧；</p>
<p>&nbsp;<br><strong>六个建议<br></strong>&nbsp;●学会与现实和谐共处；<br>&nbsp;●尽快面向不同领域建立跨平台构件标准；<br>&nbsp;●支持各领域已经形成的基础库不断完善；<br>&nbsp;●支持相关工具厂商，迅速完善工具链；<br>&nbsp;●支持动态语言的发展；<br>&nbsp;●面向产业挑战创新发展；</p>
<p>&nbsp;</p>
<p><strong>与现实和谐共处<br></strong>&nbsp;●承认C++只适合这个世界的一部分工作，快乐地与其他语言共同协作；<br>&nbsp;●告别妄自尊大和保守傲慢；<br>&nbsp;●尊重其他社群的专业能力和成绩；<br>&nbsp;●坦率承认C++在很多场合并非理想选择；<br>&nbsp;●在C++擅长的领域保持锐意。</p>
<p><br><strong>跨平台构件标准<br></strong>&nbsp;●C++迈向未来的关键技术步骤；<br>&nbsp;●尽可能支持现有的成熟方案；<br>&nbsp;●在不同尺度的平台上可能需要不同的标准；</p>
<p>&nbsp;</p>
<p><strong>支持成熟的基础库<br></strong>&nbsp;●基本组件：STL和Boost（部分）<br>&nbsp;●网络和系统编程：ACE<br>&nbsp;●分布式计算：ICE<br>&nbsp;●GUI：Qt<br>&nbsp;●Windows：MFC/ATL/WTL<br>&nbsp;●科学计算：MTL</p>
<p>&nbsp;</p>
<p><strong>完善工具链<br></strong>&nbsp;●C++用的GC；<br>&nbsp;●Code Review工具；<br>&nbsp;●内存错误排查工具；<br>&nbsp;●测试工具；<br>&nbsp;●MDA工具；<br>&nbsp;●文档工具；<br>&nbsp;●持续集成工具；<br>&nbsp;●运行录像工具。</p>
<p><br><strong>支持动态语言<br></strong>&nbsp;●动态语言是软件技术发展的一个重要方向，几年后会成为主流。<br>&nbsp;●目前几个流行动态语言天生与C/C++具有亲缘关系；<br>&nbsp;●加强对动态语言的友好性，是C++未来发展的一项重要任务；<br>&nbsp;●从这个角度来看待C++/CLI，我们应该持积极态度；<br>&nbsp;●Little Language问题；</p>
<p><br><strong>迎接产业新挑战</strong><br>&nbsp;●多核CPU带来根本性挑战，C++有责任挺身而出，为其他语言铺平前进道路；<br>&nbsp;●安全性问题，C/C++实际上是给整个产业拖了后腿，对此我们应当充分关注，积极改进；<br>&nbsp;●将STL思想精华发扬光大。<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/22600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-04-22 19:50 <a href="http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET性能优化方面的总结（4） JavaScript</title><link>http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 07 Apr 2007 05:17:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/21449.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/21449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/21449.html</trackback:ping><description><![CDATA[<p><br><strong>&nbsp;&nbsp;&nbsp; 4.1 JScript性能优化的基本原则</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽可能少地减少执行次数。毕竟对解释语言来说，每一个执行步骤，都需要和解释引擎做一次交互。<br><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽可能使用语言内置的功能，比如串链接。<br><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;尽可能使用系统提供的API来进行优化。因为这些API是编译好的二进制代码，执行效率很高。<br><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;书写最正确的代码。容错功能是要付出性能代价的。<br><br><strong>&nbsp;&nbsp;&nbsp; 4.2 JScript语言本身的优化</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>4.2.1 变量<br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽量使用局部变量。<br><strong>&nbsp;&nbsp;&nbsp; </strong>因为全局变量其实是全局对象的成员，而局部变量在栈上定义，优先查找，性能相对于全局变量要高。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽量在一个语句中做定义变量和赋值。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;省略不必要的变量定义。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果变量的定义可以被一个常量替代，就直接使用常量。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;使用Object语法对对象赋值。<br><strong>&nbsp;&nbsp;&nbsp; </strong>Object的赋值语法在操作复杂对象时效率更高。<br><strong>&nbsp;&nbsp;&nbsp; </strong>例如，可以将下面的代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">car&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Object();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.make&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Honda</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.model&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Civic</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.transmission&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">manual</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.miles&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.condition&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">needs&nbsp;work</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span></div>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>替换成：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_6_122_Open_Image onclick="this.style.display='none'; Codehighlighter1_6_122_Open_Text.style.display='none'; Codehighlighter1_6_122_Closed_Image.style.display='inline'; Codehighlighter1_6_122_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_6_122_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_6_122_Closed_Text.style.display='none'; Codehighlighter1_6_122_Open_Image.style.display='inline'; Codehighlighter1_6_122_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">car&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_6_122_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_6_122_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;make:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Honda</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;model:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Civic</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;transmission:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">manual</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;miles:&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;condition:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">needs&nbsp;work</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 4.2.2 对象缓存<br>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;缓存对象查找的中间结果。<br><strong>&nbsp;&nbsp;&nbsp; </strong>因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;缓存创建时间较长的对象。<br><strong>&nbsp;&nbsp;&nbsp; </strong>自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用，应采用缓存的方式。</p>
<p><strong>&nbsp;&nbsp;&nbsp; 4.2.3 字符串操作</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;使用"+=" 追加字符串，使用"+"来连接字符串。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果要连接多个字符串，应该使用"+"，如：<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=a;<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=b;<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=c;<br><strong>&nbsp;&nbsp;&nbsp; </strong>应该写成<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=a + b + c；</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;连接大量的字符串，应使用Array的join方法。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果是收集字符串，最好使用JavaScript数组缓存，最后使用join方法连接起来，如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;buf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Array();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_53_83_Open_Image onclick="this.style.display='none'; Codehighlighter1_53_83_Open_Text.style.display='none'; Codehighlighter1_53_83_Closed_Image.style.display='inline'; Codehighlighter1_53_83_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_53_83_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_53_83_Closed_Text.style.display='none'; Codehighlighter1_53_83_Open_Image.style.display='inline'; Codehighlighter1_53_83_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_53_83_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_53_83_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;buf.push(i.toString());<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;all&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;buf.join(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">);</span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 4.2.4 类型转换<br>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;使用Math.floor()或者Math.round()将浮点数转换成整型。<br><strong>&nbsp;&nbsp;&nbsp; </strong>浮点数转换成整型，这个更容易出错，很多人喜欢使用parseInt()，其实parseInt()是用于将字符串转换成数字，而不是浮点数和整型之间的转换，我们应该使用Math.floor()或者Math.round()。<br>对象查找中的问题不一样，Math是内部对象，所以Math.floor()其实并没有多少查询方法和调用的时间，速度是最快的。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;自定义的对象，推荐定义和使用toString()方法来进行类型转换。<br><strong>&nbsp;&nbsp;&nbsp; </strong>对于自定义的对象，如果定义了toString()方法来进行类型转换的话，推荐显式调用toString()。因为内部的操作在尝试所有可能性之后，会尝试对象的toString()方法尝试能否转化为String，所以直接调用这个方法效率会更高。</p>
<p><strong>&nbsp;&nbsp;&nbsp; 4.2.5 循环的优化<br>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽可能少使用for(in)循环。<br><strong>&nbsp;&nbsp;&nbsp; </strong>在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;预先计算collection的length。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如：将<br>&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; collection.length; i++)<br><strong>&nbsp;&nbsp;&nbsp; </strong>替换成：<br>&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0,&nbsp;len = collection.length; i &lt;&nbsp;len; i++)<br><strong>&nbsp;&nbsp;&nbsp; </strong>效果会更好，尤其是在大循环中。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;尽量减少循环内的操作。<br><strong>&nbsp;&nbsp;&nbsp; </strong>循环内的每个操作，都会被放大为循环次数的倍数。所以，大循环内微小的改进，在性能的整体提升上都是可观的。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;使用循环替代递归。<br>相比循环，递归的效率更差一些。递归的优点是在形式上更自然一些。所以，在不影响代码的维护性的前提下，用循环替代递归。</p>
<p><strong>&nbsp;&nbsp;&nbsp; 4.2.6 其它方面</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽量使用语言内置的语法。<br><strong>&nbsp;&nbsp;&nbsp; </strong>"var arr = [&#8230;];"和"var arr = new Array(&#8230;);"是等效的，但是前者的效能优于后者。同样，"var foo = {};"的方式也比"var foo = new Object();"快；"var reg = /../;"要比"var reg=new RegExp()"快。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽量不要使用eval。<br>使用eval，相当于在运行时再次调用解释引擎，对传入的内容解释运行，需要消耗大量时间。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;使用prototype代替closure。<br><strong>&nbsp;&nbsp;&nbsp; </strong>使用closure在性能和内存消耗上都是不利的。如果closure使用量过大，这就会成为一个问题。所以，尽量将：<br>&nbsp;&nbsp;&nbsp;&nbsp; this.methodFoo = function()<br>替换成：<br>&nbsp;&nbsp;&nbsp;&nbsp; MyClass.protoype.methodFoo = function()<br>和closure存在于对象实例之中不同，prototype存在于类中，被该类的所有的对象实例共享。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;避免使用with语句。<br><strong>&nbsp;&nbsp;&nbsp; </strong>With语句临时扩展对象查找的范围，节省了文字的录入时间，但付出了更多的执行时间。因为每个给出的名称都要在全局范围查找。所以，可以将下面的代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">with</span><span style="COLOR: #000000">&nbsp;(document.formname)<br><img id=Codehighlighter1_25_79_Open_Image onclick="this.style.display='none'; Codehighlighter1_25_79_Open_Text.style.display='none'; Codehighlighter1_25_79_Closed_Image.style.display='inline'; Codehighlighter1_25_79_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_25_79_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_25_79_Closed_Text.style.display='none'; Codehighlighter1_25_79_Open_Image.style.display='inline'; Codehighlighter1_25_79_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_25_79_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_25_79_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;field1.value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">one</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;field2.value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">two</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>变更为：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;form&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;document.formname;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>form.field1.value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">one</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>form.field2.value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">two</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 4.3 DOM相关</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>4.3.1 创建DOM节点<br><strong>&nbsp;&nbsp;&nbsp; </strong>相比较通过document.write来给页面生成内容，找一个容器元素（比如指定一个div或者span）并设置他们的innerHTML效率更高。<br><strong>&nbsp;&nbsp;&nbsp; </strong>而设置innerHTML的方式比通过createElement方法创建节点的效率更高。事实上，设置元素的innerHTML是创建节点效率最高的一种方式。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果必须使用createElement方法，而如果文档中存在现成的样板节点，应该是用cloneNode()方法。因为使用createElement()方法之后，你需要设置多次元素的属性，使用cloneNode()则可以减少属性的设置次数。同样，如果需要创建很多元素，应该先准备一个样板节点。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.3.2 离线操作大型的DOM树<br><strong>&nbsp;&nbsp;&nbsp; </strong>在添加一个复杂的DOM树时，可以先构造，构造结束后再将其添加到DOM数的适当节点。这能够节省界面刷新的时间。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>同样，在准备编辑一个复杂的树时，可以先将树从DOM树上删除，等编辑结束后再添加回来。<br>&nbsp;<br><strong>&nbsp;&nbsp;&nbsp; 4.3.3 对象查询<br>&nbsp;&nbsp;&nbsp; </strong>使用[""]查询要比.item()更快。调用.item()增加了一次查询和函数的调用。<br><br><strong>&nbsp;&nbsp;&nbsp; 4.3.4 定时器<br>&nbsp;&nbsp;&nbsp; </strong>如果针对的是不断运行的代码，不应该使用setTimeout，而应该用setInterval。setTimeout每次要重新设置一个定时器。<br><br><strong>&nbsp;&nbsp;&nbsp; 4.4 其他</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽量减小文件尺寸。<br><strong>&nbsp;&nbsp;&nbsp; </strong>将JScript文件中无关的空行、空格、注释去掉，有助于减小JS文件的尺寸，提高下载的时间。（可以通过工具来支持代码发布）<br><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽量不要在同一个Page内同时引用JScript和VBScript引擎<br><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;将Page内的JScript移入到单独的JS文件中。<br><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;将Page内的JScript放置在Page的最下面，有助于提高页面的响应速度。<br><strong>&nbsp;&nbsp;&nbsp; </strong>5.&nbsp;利用cache，减少JScript文件的下载次数<br><strong>&nbsp;&nbsp;&nbsp; </strong>6.&nbsp;在HTML内书写JScript文件的URL时，注意统一大小写。这样可以利用前面URL缓存的文件。<br><strong>&nbsp;&nbsp;&nbsp; </strong>7.&nbsp;推荐使用JScript Lint检查Javascript代码。毕竟，对JScript引擎来说，最容易理解的JScript代码，执行的效率也就最高。<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/21449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-04-07 13:17 <a href="http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET性能优化方面的总结（3） Asp.Net </title><link>http://www.cppblog.com/andxie99/archive/2007/04/07/21437.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 07 Apr 2007 01:32:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/04/07/21437.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/21437.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/04/07/21437.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/21437.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/21437.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; <strong>3.1 减少往返行程（Reduce Round Trips）</strong><br>&nbsp;&nbsp;&nbsp; 使用下面的方法可以减少Web服务器和Browser之间的往返行程：<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;为Browser启用缓存<br>&nbsp;&nbsp;&nbsp; 如果呈现的内容是静态的或变化周期较长，应启用Browser缓存，避免发出冗余的http请求。</p>
<p>&nbsp;&nbsp;&nbsp; 2.&nbsp;缓冲页面输出<br>&nbsp;&nbsp;&nbsp; 如果可能，则尽量缓冲页面输出，处理结束后再一次传送到客户端，这可以避免频繁传递小块内容所造成的多次网络交互。由于这种方式在页面处理结束之前客户端无法看到页面内容，因此如果一个页面的尺寸较大的话，可考虑使用Response.Flush方法。该方法强制输出迄今为止在缓冲区中的内容，你应当采用合理的算法控制调用Response.Flush方法的次数。</p>
<p>&nbsp;&nbsp;&nbsp; 3.&nbsp;使用Server.Transfer重定向请求<br>&nbsp;&nbsp;&nbsp; 使用Server.Transfer方法重定向请求优于Response.Redirect方法。原因是Response.Redirect会向Broswer回送一个响应头，在响应头中指出重定向的URL，之后Brower使用新的URL重新发出请求。而Server.Transfer方法直接是一个简单的服务端调用，完全没有这些开销！<br>&nbsp;&nbsp;&nbsp; 需要注意Server.Transfer有局限性：第一，它会跳过安全检查；第二，只适用于在同一Web应用内的页面间跳转。<br><br>&nbsp;&nbsp;&nbsp; <strong>3.2 避免阻塞和长时间的作业<br></strong>&nbsp;&nbsp;&nbsp; 如果需要运行阻塞或长时间运行的操作，可以考虑使用异步调用的机制，以便Web服务器能够继续处理其它的请求。<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;使用异步方式调用Web服务和远程对象<br>&nbsp;&nbsp;&nbsp; 只要有可能就要避免在请求的处理过程中对Web服务和远程对象的同步调用，因为它占用的是的ASP.NET 线程池中的工作线程，这将直接影响Web服务器响应其它请求的能力。</p>
<p>&nbsp;&nbsp;&nbsp; 2.&nbsp;考虑给不需要返回值的Web方法或远程对象的方法添加OneWay属性<br>&nbsp;&nbsp;&nbsp; 这种模式能让Web Server调用之后就立即返回。可根据实际情况决定是否使用这种方法。</p>
<p>&nbsp;&nbsp;&nbsp; 3.&nbsp;使用工作队列<br>&nbsp;&nbsp;&nbsp; 将作业提交到服务器上的工作队列中。客户端通过发送请求来轮询作业的执行结果。<br><br>&nbsp;&nbsp;&nbsp; <strong>3.3 使用缓存</strong><br>&nbsp;&nbsp;&nbsp; 缓存能在很大程度上决定ASP.NET应用的最终性能。Asp.net支持页面输出缓存和页面部分缓存，并提供Cache API，供应用程序缓存自己的数据。是否使用缓存可考虑下面的要点：<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;识别创建与访问代价较大的数据<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;评估需要缓存数据的易变性<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;评估数据的使用频次<br>&nbsp;&nbsp;&nbsp; 4.&nbsp;将要缓存数据中易变数据和不变数据分离，只缓存不变数据<br>&nbsp;&nbsp;&nbsp; 5.&nbsp;选择合适的缓存机制（除Asp.net Cache外，Application state和Session state也可以作为缓存使用）<br><br>&nbsp;&nbsp;&nbsp; <strong>3.4 多线程<br></strong>&nbsp;&nbsp;&nbsp; 1.&nbsp;避免在请求处理过程中创建线程<br>&nbsp;&nbsp;&nbsp; 在执行请求的过程中创建线程是一种代价较大的操作，会严重影响Web Server的性能。如果后续的操作必须用线程完成，建议通过thread pool来创建/管理线程。</p>
<p>&nbsp;&nbsp;&nbsp; 2.&nbsp;不要依赖线程数据槽或线程静态变量<br>&nbsp;&nbsp;&nbsp; 由于执行请求的线程是ASP.NET thread pool中的工作线程，同一个Client的两次请求不一定由相同的线程来处理。 </p>
<p>&nbsp;&nbsp;&nbsp; 3.&nbsp;避免阻塞处理请求的线程<br>参考"避免阻塞和长时间的作业"小节。</p>
<p>&nbsp;&nbsp;&nbsp; 4.&nbsp;避免异步调用<br>&nbsp;&nbsp;&nbsp; 这和1的情况类似。异步调用会导致创建新的线程，增加服务器的负担。所以，如果没有并发的作业要执行，就不要执行异步调用。<br><br>&nbsp;&nbsp;&nbsp; 3<strong>.5 系统资源<br></strong>&nbsp;&nbsp;&nbsp; 1.&nbsp;考虑实现资源池以提升性能<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;明确地调用Dispose或Close释放系统资源<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;不要缓存或长时间占用资源池中的资源<br>&nbsp;&nbsp;&nbsp; 4.&nbsp;尽可能晚的申请，尽可能早的释放<br><br>&nbsp;&nbsp;&nbsp; <strong>3.6 页面处理</strong><br>&nbsp;&nbsp;&nbsp; 1.&nbsp;尽量减小Page的尺寸<br>&nbsp;&nbsp;&nbsp; 包括缩短控件的名称、CSS的class的名称、去掉无谓空行和空格、禁用不需要的ViewState<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;启用页面输出的缓冲区（Buffer）<br>&nbsp;&nbsp;&nbsp; 如果Buffer的机制被关闭，可以用下面的方法打开。<br>&nbsp;&nbsp;&nbsp;&nbsp; 使用程序打开页面输出缓存：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.BufferOutput = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 使用@Page开关打开页面输出缓冲机制：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%@ Page Buffer = "true" %&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 使用Web.config或Machine.config配置文件的&lt;pages&gt;节点：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;pages buffer="true" &#8230;&gt;<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;利用Page.IsPostBack优化页面输出<br>&nbsp;&nbsp;&nbsp; 4.&nbsp;通过分离页面的不同的内容，来提高缓存效率和减少呈现的时间&nbsp;<br>&nbsp;&nbsp;&nbsp; 5.&nbsp;优化复杂和代价较大的循环&nbsp;<br>&nbsp;&nbsp;&nbsp; 6.&nbsp;合理利用客户端的计算资源，将一些操作转移到客户端进行<br><br>&nbsp;&nbsp;&nbsp; <strong>3.7 ViewState<br></strong>&nbsp;&nbsp;&nbsp; ViewState是Asp.net为服务端控件在页面回传之间跟踪状态信息而设计的一种机制。<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;关闭ViewState<br>&nbsp;&nbsp;&nbsp; 如果不需要跟踪页面状态，例如页面不会 回传（PostBack）、不需要处理服务端控件事件或者每次页面刷新时都会重新计算控件内容，那么就不需要用ViewState来记录页面状态了。可以对特定的WebControl设置EnableViewState属性，也可以在页面一级设置：<br>&lt;%@ Page EnableViewState="false" %&gt;</p>
<p>&nbsp;&nbsp;&nbsp; 2.&nbsp;在恰当的时间点初始化控件属性<br>&nbsp;&nbsp;&nbsp; ASP.NET的控件在执行构造函数、初始化的期间设置的属性不会被跟踪变化；而在初始化阶段之后对属性的修改都会被跟踪，并最终记录到IE页面的__VIEWSTATE之中。所以，选择合理的初始化控件属性的执行点，能有效的减小页面尺寸。</p>
<p>&nbsp;&nbsp;&nbsp; 3.&nbsp;谨慎选择放到ViewState中的内容<br>&nbsp;&nbsp;&nbsp; 放到ViewState中的内容会被序列化/反序列化，Asp.net为String、Integer、Boolean等基本类型的序列化做了优化，如果Array、ArrayList、HashTable存储的是基本类型效率也较高，但其它类型则需要提供类型转换器（Type Converter），否则将使用代价昂贵的二进制序列化程序。<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/21437.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-04-07 09:32 <a href="http://www.cppblog.com/andxie99/archive/2007/04/07/21437.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET性能优化方面的总结（2） Ado.Net</title><link>http://www.cppblog.com/andxie99/archive/2007/04/02/21119.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Mon, 02 Apr 2007 13:59:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/04/02/21119.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/21119.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/04/02/21119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/21119.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/21119.html</trackback:ping><description><![CDATA[<p><strong>2. Ado.Net<br></strong><br><strong>&nbsp;&nbsp;&nbsp; 2.1 应用Ado.net的一些思考原则</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;根据数据使用的方式来设计数据访问层<br><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;缓存数据，避免不必要的操作<br><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;使用服务帐户进行连接<br><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;必要时申请，尽早释放<br><strong>&nbsp;&nbsp;&nbsp; </strong>5.&nbsp;关闭可关闭的资源<br><strong>&nbsp;&nbsp;&nbsp; </strong>6.&nbsp;减少往返<br><strong>&nbsp;&nbsp;&nbsp; </strong>7.&nbsp;仅返回需要的数据<br><strong>&nbsp;&nbsp;&nbsp; </strong>8.&nbsp;选择适当的事务类型<br><strong>&nbsp;&nbsp;&nbsp; </strong>9.&nbsp;使用存储过程<br><br><strong>&nbsp;&nbsp;&nbsp; 2.2 Connection</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>数据库连接是一种共享资源，并且打开和关闭的开销较大。Ado.net默认启用了连接池机制，关闭连接不会真的关闭物理连接，而只是把连接放回到连接池中。因为池中共享的连接资源始终是有限的，如果在使用连接后不尽快关闭连接，那么就有可能导致申请连接的线程被阻塞住，影响整个系统的性能表现。<br><strong>&nbsp;&nbsp;</strong>&nbsp;<strong> 2.2.1 在方法中打开和关闭连接</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>这个原则有几层含义：<br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;主要目的是为了做到必要时申请和尽早释放<br><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;不要在类的构造函数中打开连接、在析构函数中释放连接。因为这将依赖于垃圾回收，而垃圾回收只受内存影响，回收时机不定<br><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;不要在方法之间传递连接，这往往导致连接保持打开的时间过长</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>这里强调一下在方法之间传递连接的危害：曾经在压力测试中遇到过一个测试案例，当增大用户数的时候，这个案例要比别的案例早很久就用掉连接池中的所有连接。经分析，就是因为A方法把一个打开的连接传递到了B方法，而B方法又调用了一个自行打开和关闭连接的C方法。在A方法的整个运行期间，它至少需要占用两条连接才能够成功工作，并且其中的一条连接占用时间还特别长，所以造成连接池资源紧张，影响了整个系统的可伸缩性！<br><br><strong>&nbsp;&nbsp;&nbsp; 2.2.2 显式关闭连接</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>Connection对象本身在垃圾回收时可以被关闭，而依赖垃圾回收是很不好的策略。推荐使用using语句显式关闭连接，如下例：&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;(SqlConnection&nbsp;conn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SqlConnection(connString))<br><img id=Codehighlighter1_59_86_Open_Image onclick="this.style.display='none'; Codehighlighter1_59_86_Open_Text.style.display='none'; Codehighlighter1_59_86_Closed_Image.style.display='inline'; Codehighlighter1_59_86_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_59_86_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_59_86_Closed_Text.style.display='none'; Codehighlighter1_59_86_Open_Image.style.display='inline'; Codehighlighter1_59_86_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_59_86_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_59_86_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;conn.Open();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Dispose&nbsp;is&nbsp;automatically&nbsp;called&nbsp;on&nbsp;the&nbsp;conn&nbsp;variable&nbsp;here</span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 2.2.3 确保连接池启用<br>&nbsp;&nbsp;&nbsp; </strong>Ado.net是为每个不同的连接串建立连接池，因此应该确保连接串不会出现与具体用户相关的信息。另外，要注意连接串是大小写敏感的。<br><strong>&nbsp;&nbsp;&nbsp; 2.2.4 不要缓存连接<br>&nbsp;&nbsp;&nbsp; </strong>例如，把连接缓存到Session或Application中。在启用连接池的情况下，这种做法没有任何意义。<br><strong>&nbsp;&nbsp;&nbsp; 2.3 Command<br>&nbsp;&nbsp;&nbsp; 2.3.1 使用ExecuteScalar和ExecuteNonQuery<br>&nbsp;&nbsp;&nbsp; </strong>如果想返回像Count(*)、Sum(Price)或Avg(Quantity)那样的单值，可以使用ExecuteScalar方法。ExecuteScalar返回第一行第一列的值，将结果集作为标量值返回。因为单独一步就能完成，所以ExecuteScalar不仅简化了代码，还提高了性能。<br>&nbsp;&nbsp;&nbsp; 使用不返回行的SQL语句时，例如修改数据（INSERT、UPDATE或DELETE）或仅返回输出参数或返回值，请使用ExecuteNonQuery。这避免了用于创建空DataReader的任何不必要处理。<br><strong>&nbsp;&nbsp;&nbsp; 2.3.2 使用Prepare<br>&nbsp;&nbsp;&nbsp; </strong>当需要重复执行同一SQL语句多次，可考虑使用Prepare方法提升效率。需要注意的是，如果只是执行一次或两次，则完全没有必要。例如：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">cmd.CommandText&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">insert&nbsp;into&nbsp;Table1&nbsp;(&nbsp;Col1,&nbsp;Col2&nbsp;)&nbsp;values&nbsp;(&nbsp;@val1,&nbsp;@val2&nbsp;)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters.Add(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">@val1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;SqlDbType.Int,&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Col1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cms.Parameters.Add(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">@val2</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;SqlDbType.NChar,&nbsp;</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Col2</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">].Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">XXX</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Prepare();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.ExecuteNonQuery();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">].Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">YYY</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.ExecuteNonQuery();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.Parameters[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">].Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ZZZ</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>cmd.ExecuteNonQuery();</span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 2.3.3 使用绑定变量</strong> <span style="COLOR: red">★<br></span><strong>&nbsp;&nbsp;&nbsp; </strong>SQL语句需要先被编译成执行计划，然后再执行。如果使用绑定变量的方式，那么这个执行计划就可以被后续执行的SQL语句所复用。而如果直接把参数合并到了SQL语句中，由于参数值千变万化，执行计划就难以被复用了。例如上面Prepare一节给出的示例，如果把参数值直接写到insert语句中，那么上面的四次调用将需要编译四次执行计划。<br><strong>&nbsp;&nbsp;&nbsp; </strong>为避免这种情况造成性能损失，要求一律使用绑定变量方式。<br><strong>&nbsp;&nbsp;&nbsp; 2.4 DataReader<br>&nbsp;&nbsp;&nbsp; </strong>DataReader最适合于访问只读的单向数据集。与DataSet不同，数据集并不全部在内存中，而是随不断发出的read请求，一旦发现数据缓冲区中的数据均被读取，则从数据源传输一个数据缓冲区大小的数据块过来。另外，DataReader保持连接，DataSet则与连接断开。<br><strong>&nbsp;&nbsp;&nbsp; 2.4.1 显式关闭DataReader<br>&nbsp;&nbsp;&nbsp; </strong>与连接类似，也需要显式关闭DataReader。另外，如果与DataReader关联的Connection仅为DataReader服务的话，可考虑使用Command对象的ExecuteReader(CommandBehavior.CloseConnection)方式。这可以保证当DataReader关闭时，同时自动关闭Connection。<br><strong>&nbsp;&nbsp;&nbsp; 2.4.2 用索引号访问代替名称索引号访问属性<br>&nbsp;&nbsp;&nbsp; </strong>从Row中访问某列属性，使用索引号的方式比使用名称方式有细微提高。如果会被频繁调用，例如在循环中，那么可考虑此类优化。示例如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">cmd.CommandText&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">select&nbsp;Col1,&nbsp;Col2&nbsp;from&nbsp;Table1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>SqlDataReader&nbsp;dr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;cmd.ExecuteReader();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;col1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dr.GetOrdinal(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Col1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;col2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dr.GetOrdinal(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Col2</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(dr.Read())<br><img id=Codehighlighter1_180_233_Open_Image onclick="this.style.display='none'; Codehighlighter1_180_233_Open_Text.style.display='none'; Codehighlighter1_180_233_Closed_Image.style.display='inline'; Codehighlighter1_180_233_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_180_233_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_180_233_Closed_Text.style.display='none'; Codehighlighter1_180_233_Open_Image.style.display='inline'; Codehighlighter1_180_233_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_180_233_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_180_233_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(&nbsp;dr[col1]&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">_</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;dr[col2]);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 2.4.3 使用类型化方法访问属性<br>&nbsp;&nbsp;&nbsp; </strong>从Row中访问某列属性，用GetString、GetInt32这种显式指明类型的方法，其效率较通用的GetValue方法有细微提高，因为不需要做类型转换。<br><strong>&nbsp;&nbsp;&nbsp; 2.4.4 使用多数据集</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>部分场景可以考虑一次返回多数据集来降低网络交互次数，提升效率。示例如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">cmd.CommandText&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">StoredProcedureName</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;The&nbsp;stored&nbsp;procedure&nbsp;returns&nbsp;multiple&nbsp;result&nbsp;sets.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">SqlDataReader&nbsp;dr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;cmd.ExecuteReader();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(dr.read())<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read&nbsp;first&nbsp;result&nbsp;set</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>dr.NextResult();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(dr.read())<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;</span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 2.5 DataSet</strong><br><strong>&nbsp;&nbsp;&nbsp; 2.5.1 利用索引加快查找行的效率</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>如果需要反复查找行，建议增加索引。有两种方式：<br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;设置DataTable的PrimaryKey<br><strong>&nbsp;&nbsp;&nbsp; </strong>适用于按PrimaryKey查找行的情况。注意此时应调用DataTable.Rows.Find方法，一般惯用的Select方法不能利用索引。<br><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;使用DataView<br><strong>&nbsp;&nbsp;&nbsp; </strong>适用于按Non-PrimaryKey查找行的情况。可为DataTable创建一个DataView，并通过SortOrder参数指示建立索引。此后使用Find或FindRows查找行。<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/21119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-04-02 21:59 <a href="http://www.cppblog.com/andxie99/archive/2007/04/02/21119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruminations on C++ 中的代理类Demo</title><link>http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Thu, 29 Mar 2007 14:44:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/20899.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/20899.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/20899.html</trackback:ping><description><![CDATA[看Ruminations on C++ 的时候照着写的，简单的框架，留作备份吧。<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;代理类&nbsp;Demo<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;将继承和容器共用，迫使我们要处理两个问题：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;控制内存分配和把不同类型的对象放入同一个容器中。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;代理类的每个对象都代表另一个对象，该对象可以是<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位于一个完整继承层次中的任何类的对象。通过在容器中<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;用代理对象而不是对象本身来解决以上两个问题</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">process.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;system()</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;所有交通工具的基类</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Vehicle<br><img id=Codehighlighter1_250_365_Open_Image onclick="this.style.display='none'; Codehighlighter1_250_365_Open_Text.style.display='none'; Codehighlighter1_250_365_Closed_Image.style.display='inline'; Codehighlighter1_250_365_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_250_365_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_250_365_Closed_Text.style.display='none'; Codehighlighter1_250_365_Open_Image.style.display='inline'; Codehighlighter1_250_365_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_250_365_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_250_365_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;动态复制</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;copy()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;虚析构函数</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_362_363_Open_Image onclick="this.style.display='none'; Codehighlighter1_362_363_Open_Text.style.display='none'; Codehighlighter1_362_363_Closed_Image.style.display='inline'; Codehighlighter1_362_363_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_362_363_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_362_363_Closed_Text.style.display='none'; Codehighlighter1_362_363_Open_Image.style.display='inline'; Codehighlighter1_362_363_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Vehicle()&nbsp;</span><span id=Codehighlighter1_362_363_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_362_363_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;交通工具的代理类</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate<br><img id=Codehighlighter1_404_694_Open_Image onclick="this.style.display='none'; Codehighlighter1_404_694_Open_Text.style.display='none'; Codehighlighter1_404_694_Closed_Image.style.display='inline'; Codehighlighter1_404_694_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_404_694_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_404_694_Closed_Text.style.display='none'; Codehighlighter1_404_694_Open_Image.style.display='inline'; Codehighlighter1_404_694_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_404_694_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_404_694_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;无参构造函数，用于创建数组</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;用Vehicle&nbsp;及其派生类构造</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Vehicle</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">VehicleSurrogate();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;拷贝及赋值</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Vehicle&nbsp;的方法</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_742_743_Open_Image onclick="this.style.display='none'; Codehighlighter1_742_743_Open_Text.style.display='none'; Codehighlighter1_742_743_Closed_Image.style.display='inline'; Codehighlighter1_742_743_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_742_743_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_742_743_Closed_Text.style.display='none'; Codehighlighter1_742_743_Open_Image.style.display='inline'; Codehighlighter1_742_743_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>VehicleSurrogate::VehicleSurrogate()&nbsp;:&nbsp;p(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_742_743_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_742_743_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_813_814_Open_Image onclick="this.style.display='none'; Codehighlighter1_813_814_Open_Text.style.display='none'; Codehighlighter1_813_814_Closed_Image.style.display='inline'; Codehighlighter1_813_814_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_813_814_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_813_814_Closed_Text.style.display='none'; Codehighlighter1_813_814_Open_Image.style.display='inline'; Codehighlighter1_813_814_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>VehicleSurrogate::VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Vehicle</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;v)&nbsp;:&nbsp;p(v.copy())&nbsp;</span><span id=Codehighlighter1_813_814_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_813_814_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>VehicleSurrogate::VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;vs)&nbsp;<br><img id=Codehighlighter1_910_911_Open_Image onclick="this.style.display='none'; Codehighlighter1_910_911_Open_Text.style.display='none'; Codehighlighter1_910_911_Closed_Image.style.display='inline'; Codehighlighter1_910_911_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_910_911_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_910_911_Closed_Text.style.display='none'; Codehighlighter1_910_911_Open_Image.style.display='inline'; Codehighlighter1_910_911_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>:&nbsp;p(vs.p&nbsp;</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">&nbsp;vs.p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">copy()&nbsp;:&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_910_911_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_910_911_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>VehicleSurrogate&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate::</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;vs)<br><img id=Codehighlighter1_990_1072_Open_Image onclick="this.style.display='none'; Codehighlighter1_990_1072_Open_Text.style.display='none'; Codehighlighter1_990_1072_Closed_Image.style.display='inline'; Codehighlighter1_990_1072_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_990_1072_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_990_1072_Closed_Text.style.display='none'; Codehighlighter1_990_1072_Open_Image.style.display='inline'; Codehighlighter1_990_1072_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_990_1072_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_990_1072_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(p&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;vs.p)<br><img id=Codehighlighter1_1009_1055_Open_Image onclick="this.style.display='none'; Codehighlighter1_1009_1055_Open_Text.style.display='none'; Codehighlighter1_1009_1055_Closed_Image.style.display='inline'; Codehighlighter1_1009_1055_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1009_1055_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1009_1055_Closed_Text.style.display='none'; Codehighlighter1_1009_1055_Open_Image.style.display='inline'; Codehighlighter1_1009_1055_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1009_1055_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1009_1055_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;p;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;vs.p&nbsp;</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">&nbsp;vs.p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">copy()&nbsp;:&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_1113_1125_Open_Image onclick="this.style.display='none'; Codehighlighter1_1113_1125_Open_Text.style.display='none'; Codehighlighter1_1113_1125_Closed_Image.style.display='inline'; Codehighlighter1_1113_1125_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1113_1125_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1113_1125_Closed_Text.style.display='none'; Codehighlighter1_1113_1125_Open_Image.style.display='inline'; Codehighlighter1_1113_1125_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>VehicleSurrogate::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">VehicleSurrogate()&nbsp;</span><span id=Codehighlighter1_1113_1125_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1113_1125_Open_Text><span style="COLOR: #000000">{&nbsp;delete&nbsp;p;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate::start()<br><img id=Codehighlighter1_1159_1216_Open_Image onclick="this.style.display='none'; Codehighlighter1_1159_1216_Open_Text.style.display='none'; Codehighlighter1_1159_1216_Closed_Image.style.display='inline'; Codehighlighter1_1159_1216_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1159_1216_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1159_1216_Closed_Text.style.display='none'; Codehighlighter1_1159_1216_Open_Image.style.display='inline'; Codehighlighter1_1159_1216_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1159_1216_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1159_1216_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(p)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;RoadVehicle&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Vehicle<br><img id=Codehighlighter1_1254_1420_Open_Image onclick="this.style.display='none'; Codehighlighter1_1254_1420_Open_Text.style.display='none'; Codehighlighter1_1254_1420_Closed_Image.style.display='inline'; Codehighlighter1_1254_1420_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1254_1420_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1254_1420_Closed_Text.style.display='none'; Codehighlighter1_1254_1420_Open_Image.style.display='inline'; Codehighlighter1_1254_1420_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1254_1420_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1254_1420_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start()<br><img id=Codehighlighter1_1280_1323_Open_Image onclick="this.style.display='none'; Codehighlighter1_1280_1323_Open_Text.style.display='none'; Codehighlighter1_1280_1323_Closed_Image.style.display='inline'; Codehighlighter1_1280_1323_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1280_1323_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1280_1323_Closed_Text.style.display='none'; Codehighlighter1_1280_1323_Open_Image.style.display='inline'; Codehighlighter1_1280_1323_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1280_1323_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1280_1323_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">RoadVehicle&nbsp;start.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;copy()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1349_1396_Open_Image onclick="this.style.display='none'; Codehighlighter1_1349_1396_Open_Text.style.display='none'; Codehighlighter1_1349_1396_Closed_Image.style.display='inline'; Codehighlighter1_1349_1396_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1349_1396_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1349_1396_Closed_Text.style.display='none'; Codehighlighter1_1349_1396_Open_Image.style.display='inline'; Codehighlighter1_1349_1396_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1349_1396_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1349_1396_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;(Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;RoadVehicle(</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">RoadVehicle()<br><img id=Codehighlighter1_1415_1418_Open_Image onclick="this.style.display='none'; Codehighlighter1_1415_1418_Open_Text.style.display='none'; Codehighlighter1_1415_1418_Closed_Image.style.display='inline'; Codehighlighter1_1415_1418_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1415_1418_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1415_1418_Closed_Text.style.display='none'; Codehighlighter1_1415_1418_Open_Image.style.display='inline'; Codehighlighter1_1415_1418_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1415_1418_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1415_1418_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;AutoVehicle&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;RoadVehicle<br><img id=Codehighlighter1_1463_1629_Open_Image onclick="this.style.display='none'; Codehighlighter1_1463_1629_Open_Text.style.display='none'; Codehighlighter1_1463_1629_Closed_Image.style.display='inline'; Codehighlighter1_1463_1629_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1463_1629_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1463_1629_Closed_Text.style.display='none'; Codehighlighter1_1463_1629_Open_Image.style.display='inline'; Codehighlighter1_1463_1629_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1463_1629_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1463_1629_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start()<br><img id=Codehighlighter1_1489_1532_Open_Image onclick="this.style.display='none'; Codehighlighter1_1489_1532_Open_Text.style.display='none'; Codehighlighter1_1489_1532_Closed_Image.style.display='inline'; Codehighlighter1_1489_1532_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1489_1532_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1489_1532_Closed_Text.style.display='none'; Codehighlighter1_1489_1532_Open_Image.style.display='inline'; Codehighlighter1_1489_1532_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1489_1532_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1489_1532_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">AutoVehicle&nbsp;start.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;copy()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1558_1605_Open_Image onclick="this.style.display='none'; Codehighlighter1_1558_1605_Open_Text.style.display='none'; Codehighlighter1_1558_1605_Closed_Image.style.display='inline'; Codehighlighter1_1558_1605_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1558_1605_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1558_1605_Closed_Text.style.display='none'; Codehighlighter1_1558_1605_Open_Image.style.display='inline'; Codehighlighter1_1558_1605_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1558_1605_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1558_1605_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;(Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AutoVehicle(</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">AutoVehicle()<br><img id=Codehighlighter1_1624_1627_Open_Image onclick="this.style.display='none'; Codehighlighter1_1624_1627_Open_Text.style.display='none'; Codehighlighter1_1624_1627_Closed_Image.style.display='inline'; Codehighlighter1_1624_1627_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1624_1627_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1624_1627_Closed_Text.style.display='none'; Codehighlighter1_1624_1627_Open_Image.style.display='inline'; Codehighlighter1_1624_1627_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1624_1627_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1624_1627_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_1645_1853_Open_Image onclick="this.style.display='none'; Codehighlighter1_1645_1853_Open_Text.style.display='none'; Codehighlighter1_1645_1853_Closed_Image.style.display='inline'; Codehighlighter1_1645_1853_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1645_1853_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1645_1853_Closed_Text.style.display='none'; Codehighlighter1_1645_1853_Open_Image.style.display='inline'; Codehighlighter1_1645_1853_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1645_1853_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1645_1853_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate&nbsp;pa[</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;RoadVehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;prv&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;RoadVehicle();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">prv;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;prv;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;AutoVehicle();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;RoadVehicle();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">].start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">].start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<img src ="http://www.cppblog.com/andxie99/aggbug/20899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-03-29 22:44 <a href="http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET性能优化方面的总结</title><link>http://www.cppblog.com/andxie99/archive/2007/03/24/20538.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 24 Mar 2007 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/24/20538.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/20538.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/24/20538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/20538.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/20538.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 从2004年底开始接触C#到现在也有2年多的时间了，因为有C++方面的基础，对于C#，我习惯于与C++对比。现在总结一些.NET方面的性能优化方面的经验，算是对这两年多的.NET工作经历的总结。&nbsp;&nbsp;&nbsp; 由于使用C#时间不长，欢迎各高手补充。&nbsp;&nbsp;&nbsp; 标有 ★ 表示特别重要，会严重影响性能，程序中不应出现...&nbsp;&nbsp;<a href='http://www.cppblog.com/andxie99/archive/2007/03/24/20538.html'>阅读全文</a><img src ="http://www.cppblog.com/andxie99/aggbug/20538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-03-24 17:06 <a href="http://www.cppblog.com/andxie99/archive/2007/03/24/20538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>但做善事，莫问前程......</title><link>http://www.cppblog.com/andxie99/archive/2007/03/24/20532.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 24 Mar 2007 08:34:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/24/20532.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/20532.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/24/20532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/20532.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/20532.html</trackback:ping><description><![CDATA[<p><br>生活的伟大在于，只要开始总能给你一个结果，成则给你想要的，失则给你另外一个机会</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/20532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-03-24 16:34 <a href="http://www.cppblog.com/andxie99/archive/2007/03/24/20532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类厂和COM类的关系</title><link>http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Wed, 07 Mar 2007 02:24:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/19341.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/19341.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/19341.html</trackback:ping><description><![CDATA[读过《COM技术内幕》，理一下用类厂创建COM类的过程以及之间的关系。<br><br>类厂用来抽象组件的create过程，客户不需要知道组件的详细情况，也不需要知道类厂的详细情况，只要知道CoCreateInstance可以创建组件即可。而CoCreateInstance内部调用DllGetClassObject来生成该组件的类厂，由于类厂有组件的作者撰写，所以对组件类可谓知根知底，由类厂来生成组件完全行得通，这样客户和组件就进一步划分，客户只能查询该组件是否支持某接口，而对组件的其他情况一无所知，这样的划分可以使组件和客户间的耦合更小。<br>组件如果将某接口的全部方法都实现了，就称该组件支持某接口，com并没有规定组件和接口之间是虚函数继承的关系，只是在c++中以这种方法来实现最好而已。 &nbsp; <br>&nbsp; IClassFactory说穿了就是专门构造组件的类，这样做是为了抽象，因为客户没有必要知道组件是什么，如果由客户直接构造组件，客户势必要知道组件的信息，com就失去了它的意义了，所以，规定了一个类厂（支持IClassFactory接口），每个组件的类厂都很清楚并且也只清楚该组件的信息，而客户只需要调用com库函数CoCreateInstance就可以了。&nbsp;&nbsp;&nbsp;<br>&nbsp; 创建流程图： &nbsp; <br>&nbsp; CoCreateInstance &nbsp; --&gt;&gt; &nbsp; CoGetClassObject &nbsp; --&gt;&gt; &nbsp; DllGetClassObject &nbsp; --&gt;&gt; &nbsp; new &nbsp; ClassFactory&nbsp;&nbsp;&nbsp; --&gt;&gt;IClassFactory::CreateInstance() &nbsp; --&gt;&gt; &nbsp; new &nbsp; Component 
<img src ="http://www.cppblog.com/andxie99/aggbug/19341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-03-07 10:24 <a href="http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> (转) 30岁前男人需要完成的事  </title><link>http://www.cppblog.com/andxie99/archive/2007/03/06/19295.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Tue, 06 Mar 2007 07:13:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/06/19295.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/19295.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/06/19295.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/19295.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/19295.html</trackback:ping><description><![CDATA[原文地址：<a href="http://community.csdn.net/Expert/topic/5371/5371540.xml?temp=.2728235">http://community.csdn.net/Expert/topic/5371/5371540.xml?temp=.2728235</a> 
<img src ="http://www.cppblog.com/andxie99/aggbug/19295.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-03-06 15:13 <a href="http://www.cppblog.com/andxie99/archive/2007/03/06/19295.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用IDropTarget接口同时支持文本和文件拖放（转）</title><link>http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Mon, 05 Mar 2007 04:52:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/19228.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/19228.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/19228.html</trackback:ping><description><![CDATA[<p align=justify>&nbsp;最近在写Shell Extension方面的东西，看到了这篇文章，抄在这里。<br>原文地址<a href="http://blog.csdn.net/vcbear/archive/2002/01/25/5990.aspx">http://blog.csdn.net/vcbear/archive/2002/01/25/5990.aspx</a><br>同时也找到了一个与Drag and Drop有关的例子，地址：<a href="http://www.codeproject.com/useritems/NSExtDragDrop.asp">http://www.codeproject.com/useritems/NSExtDragDrop.asp</a></p>
<font lang=ZH-CN face=宋体 size=3>
<p align=justify></p>
</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#118;&#99;&#98;&#101;&#97;&#114;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;"><font face="宋体, MS Song" size=4>vcbear</font> </a><font lang=ZH-CN face=宋体>
<p align=justify>关于</p>
</font><font face="宋体, MS Song">Windows</font> <font lang=ZH-CN face=宋体>的外壳扩展编程，拖放是比较简单的一种，在网上可以找到不少介绍这个技巧的文章。大部分是介绍使用</font> <font face="宋体, MS Song">MFC</font> <font lang=ZH-CN face=宋体>的</font> <font face="宋体, MS Song">COleDropTarget</font> <font lang=ZH-CN face=宋体>实现的，我觉得一般使用</font> <font face="宋体, MS Song">COleDropTarget</font> <font lang=ZH-CN face=宋体>已经很好了，但是我习惯在一些程序模块中，完全的不使用</font> <font face="宋体, MS Song">MFC,</font> <font lang=ZH-CN face=宋体>比如纯</font> <font face="宋体, MS Song">SDK</font> <font lang=ZH-CN face=宋体>编程</font> <font face="宋体, MS Song">,</font> <font lang=ZH-CN face=宋体>还有用在</font> <font face="宋体, MS Song">ATL</font> <font lang=ZH-CN face=宋体>的时候</font> <font face="宋体, MS Song">,MFC</font> <font lang=ZH-CN face=宋体>是相当累赘的。所以</font> <font face="宋体, MS Song">COleDropTarget</font> <font lang=ZH-CN face=宋体>在这个意义上讲不够完美。
<p align=justify>参考了</p>
</font><font face="宋体, MS Song">MSDN</font> <font lang=ZH-CN face=宋体>以及</font> <a href="http://www.codeproject.com/"><font face="宋体, MS Song">www.CodeProject.com</font> </a><font lang=ZH-CN face=宋体>的相关文章和代码（</font> <strong><font face="宋体, MS Song">by Thomas Blenkers</font> </strong><font lang=ZH-CN face=宋体>）之后，我发现拖放实际上主要使用了</font> <font face="宋体, MS Song">IDropTarget</font> <font lang=ZH-CN face=宋体>的接口方法，非常简单，不妨直接面对原始</font> <font face="宋体, MS Song">IDropTarget</font> <font lang=ZH-CN face=宋体>实现自己的拖放类。
<p align=justify>作为学习笔记，就有了这么一篇文字,以抛砖引玉：</p>
</font><strong><font color=#0000ff>
<p align=justify>IDropTarget</p>
</font></strong><font lang=ZH-CN face=宋体>是系统留给支持拖放的客户程序的一个纯虚接口，事先没有对接口的任何函数进行实现，而是让用户通过实现接口函数来接管拖放的结果。</font>IDropTarget<font lang=ZH-CN face=宋体>接口有以下成员函数：
<ul>
    <p align=justify></p>
    <li>基本</li>
</ul>
</font><font face="宋体, MS Song">COM</font><font lang=ZH-CN face=宋体>成员函数
<p>&#160;</p>
<dir>
<dir></dir></dir></font><strong><font color=#0000ff>
<p align=justify>QueryInterface </p>
<p align=justify>AddRef </p>
<p align=justify>Release </p>
<ul></ul>
    </font></strong><font lang=ZH-CN face=宋体>
    <p align=justify></p>
    <li>接管拖放事件的成员函数：
    <p>&#160;</p>
    <dir>
    <dir></dir></dir></font><strong><font color=#0000ff>
    <p align=justify>DragEnter</p>
    <p align=justify>DragOver</p>
    <p align=justify>DragLeave</p>
    <p align=justify>Drop</p>
    </font></strong><font lang=ZH-CN face=宋体>
    <p align=justify>也就是说，要在客户程序里实现以上</p>
    </font><font face="宋体, MS Song">7</font><font lang=ZH-CN face=宋体>个函数的实体。
    <p align=justify>系统在检测到拖放发生的时候，会在合适的时候依次调用客户程序里实现的</p>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>接口相应函数，检查用户在这些函数里返回的标志，决定鼠标外观表现和拖放结果。</font><font lang=ZH-CN face=宋体 size=3>
    <p>&#160;</p>
    <hr>
    <p>&#160;</p>
    </font><strong><font lang=ZH-CN face=宋体>
    <p align=justify>　</p>
    <p align=justify>实现</p>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>接口</font></strong><br>为此建立一个基类为<font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>的类：</font><strong><font face="宋体, MS Song"></font>
    <p align=justify>class CDropTargetEx : public IDropTarget </p>
    </strong>
    <p align=justify>IDropTarget<font lang=ZH-CN face=宋体>接口在</font>OLEIDL.h<font lang=ZH-CN face=宋体>里定义，为纯虚接口。</font></p>
    <p align=justify>在<font face="宋体, MS Song">CDropTargetEx</font><font lang=ZH-CN face=宋体>里依次声明接口所包含的</font><font face="宋体, MS Song">7</font><font lang=ZH-CN face=宋体>个函数，原形为：</font></p>
    <font color=#0000ff>
    <p align=justify>HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);</p>
    <p align=justify>ULONG STDMETHODCALLTYPE AddRef(void);</p>
    <p align=justify>ULONG STDMETHODCALLTYPE Release(void);</p>
    <p align=justify>HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, </p>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <p align=justify>POINTL pt, </p>
    <p align=justify>DWORD *pdwEffect);</p>
    </dir></dir></dir></dir></dir></dir></dir></dir>
    <p align=justify>HRESULT STDMETHODCALLTYPE DragEnter(IDataObject * pDataObject, </p>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <p align=justify>DWORD grfKeyState, POINTL pt, </p>
    <p align=justify>DWORD * pdwEffect);</p>
    </dir></dir></dir></dir></dir></dir></dir></dir>
    <p align=justify>HRESULT STDMETHODCALLTYPE DragLeave(void);</p>
    <p align=justify>HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, </p>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <p align=justify>DWORD grfKeyState, </p>
    <p align=justify>POINTL pt, </p>
    <p align=justify>DWORD __RPC_FAR *pdwEffect);</p>
    </dir></dir></dir></dir></dir></dir></dir></dir></font>
    <p align=justify>(<font lang=ZH-CN face=宋体>为了实现</font>Addref<font lang=ZH-CN face=宋体>计数，还有一个</font><strong>ULONG tb_RefCount</strong><font lang=ZH-CN face=宋体>成员变量是必须的。</font><strong>QueryInterface<font lang=ZH-CN face=宋体>，</font>AddRef,Release</strong><font lang=ZH-CN face=宋体>这</font>3<font lang=ZH-CN face=宋体>个函数的实现是</font>COM<font lang=ZH-CN face=宋体>知识中最基本的，请参见附例</font>)</p>
    <font lang=ZH-CN face=宋体>
    <p align=justify>在讲解</p>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>其他函数的具体实现之前，有必要介绍一下一个你可能永远不会直接调用但是确实存在的函数：</font><strong><font color=#0000ff><font face="宋体, MS Song">DoDragDrop</font></font></strong><font lang=ZH-CN face=宋体>函数.此函数在某数据源的数据被拖动的时候就被调用，它负责
    <ul>
        <p align=justify></p>
        <li>检测目标窗口是否支持拖放，发现目标窗口的</li>
    </ul>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>接口
    <p>&#160;</p>
    <p align=justify></p>
    <li>随时跟踪鼠标和键盘的状态，根据状态决定调用其</font><font face="宋体, MS Song">DrageEnter,DragMove,Drop</font><font lang=ZH-CN face=宋体>或</font><font face="宋体, MS Song">DragLeave</font><font lang=ZH-CN face=宋体>接口
    <p>&#160;</p>
    <p align=justify></p>
    <li>从这些接口获取客户程序的返回值，根据这些值和用户界面以及数据源进行交互。
    <p>&#160;</p>
    <p align=justify>可以说</p>
    </font><font face="宋体, MS Song">DoDragDrop</font><font lang=ZH-CN face=宋体>控制拖放的整个过程，我们要做的，只是将这个过程里发生的事件，接管下来并得到相应的信息，和</font><strong><font face="宋体, MS Song">DoDragDrop</font></strong><font lang=ZH-CN face=宋体>进行交互而已。了解了这一点有助于我们理解为什么通过区区一个接口</font><font face="宋体, MS Song">4</font><font lang=ZH-CN face=宋体>个函数就可以实现了拖放的效果，因为系统为我们已经做了很多。
    <p align=justify>另一个非常重要的</p>
    </font><font face="宋体, MS Song">API</font><font lang=ZH-CN face=宋体>是</font><strong><font color=#0000ff><font face="宋体, MS Song">RegisterDragDrop</font></font></strong><font lang=ZH-CN face=宋体>，这个函数的原形是这样的：</font><font color=#0000ff>
    <p align=justify>WINOLEAPI RegisterDragDrop(</p>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <p align=justify>HWND hwnd, </p>
    <p align=justify>IDropTarget * pDropTarget</p>
    <p align=justify>);</p>
    </dir></dir></dir></dir></dir></dir></font><font lang=ZH-CN face=宋体>
    <p align=justify>不用被</p>
    </font><font face="宋体, MS Song">WINOLEAPI</font><font lang=ZH-CN face=宋体>吓到，这是一个宏:</font><strong><font color=#0000ff>
    <p align=justify>#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE</p>
    </font></strong><font lang=ZH-CN face=宋体>
    <p align=justify>也就是表示一个标准的</p>
    </font><font face="宋体, MS Song">WIN API</font><font lang=ZH-CN face=宋体>函数，返回一个</font><font face="宋体, MS Song">HRESULT</font><font lang=ZH-CN face=宋体>的值。
    <p align=justify>函数</p>
    </font><strong><font face="宋体, MS Song">RegisterDragDrop</font></strong><font lang=ZH-CN face=宋体>的作用是告诉系统:某个窗口（</font><font face="宋体, MS Song">hwnd</font><font lang=ZH-CN face=宋体>参数指定）可以接受拖放，接管拖放的接口是</font><font face="宋体, MS Song">pDropTarget</font><font lang=ZH-CN face=宋体>。
    <p align=justify>记住在调用</p>
    </font><font face="宋体, MS Song">RegisterDragDrop</font><font lang=ZH-CN face=宋体>之前，一定要先调用</font><strong><font color=#0000ff><font face="宋体, MS Song">OleInitialize</font></font></strong><font lang=ZH-CN face=宋体>初始化</font><font face="宋体, MS Song">OLE</font><font lang=ZH-CN face=宋体>环境。
    <p align=justify>在类</p>
    </font><font face="宋体, MS Song">CDropTargetEx</font><font lang=ZH-CN face=宋体>里设计了一个函数</font><font color=#0000ff>
    <p align=justify>BOOL CDropTargetEx::DragDropRegister(HWND hWnd,</p>
    <p align=justify>DWORD AcceptKeyState=|MK_LBUTTON)</p>
    <p align=justify>{</p>
    </font><font lang=ZH-CN face=宋体 color=#0000ff>
    <p align=justify></p>
    </font><font color=#0000ff><font face="宋体, MS Song">if(!IsWindow(hWnd))return false;</font>
    <p align=justify>HRESULT s = ::RegisterDragDrop (hWnd,this);</p>
    <p align=justify>if(SUCCEEDED(s))</p>
    <p align=justify>{</p>
    <p align=justify>m_hTargetWnd = hWnd;</p>
    <p align=justify>m_AcceptKeyState = AcceptKeyState;</p>
    <p align=justify>return true;</p>
    <p align=justify>}</p>
    <p align=justify>else { return false; }</p>
    <p align=justify>}</p>
    </font><font lang=ZH-CN face=宋体>
    <p align=justify>在这个函数里调用</p>
    </font><font face="宋体, MS Song">RegisterDragDrop,</font><font lang=ZH-CN face=宋体>将</font><font face="宋体, MS Song">this</font><font lang=ZH-CN face=宋体>指针传入，表示本类实现了</font><font face="宋体, MS Song">IDropTarget.</font><font lang=ZH-CN face=宋体>，由本类接管拖放事件。另外顺便定义了一下拖放鼠标和键盘特性常数，对这个类来说，我希望默认的只接受鼠标左键的拖放，所以，默认的</font><font face="宋体, MS Song">AcceptKeyState</font><font lang=ZH-CN face=宋体>值是</font><strong><font face="宋体, MS Song">MK_LBUTTON</font></strong><font lang=ZH-CN face=宋体>。相关的键盘鼠标常数还有</font><strong><font face="宋体, MS Song">MK_SHIFT,MK_ALT,MK_RBOTTON,MK_MBUTTON,MK_BOTTON</font></strong><font lang=ZH-CN face=宋体>等几个，我想这个几个常数从字面上就可以理解它的意思了。这些常数可以用&#8220;位与&#8221;的操作组合。
    <p align=justify>以下具体讨论</p>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>的拖放相关接口函数（</font><font face="宋体, MS Song">4</font><font lang=ZH-CN face=宋体>个），这里的拖放对象以文本和文件为主。</font><font lang=ZH-CN face=宋体 size=3>
    <p>&#160;</p>
    <hr>
    <p>&#160;</p>
    <ul></ul>
        </font><strong><font color=#ff0000 size=4>
        <p align=justify></p>
        <li>DragEnter
        <p>&#160;</p>
        <dir></dir></font></strong><font lang=ZH-CN face=宋体>
        <p align=justify>当你用鼠标选中了某一个文件或一段文本，并且将鼠标移到某个可以接受拖放（已经调用过</p>
        </font><font face="宋体, MS Song">RegisterDragDrop</font><font lang=ZH-CN face=宋体>）的窗口里，</font><font face="宋体, MS Song">DragEnter</font><font lang=ZH-CN face=宋体>将第一时间被调用。再看一下其原形：</font><strong><font color=#0000ff>
        <p align=justify>HRESULT DragEnter( IDataObject * pDataObject,</p>
        <dir>
        <dir>
        <dir>
        <p align=justify>&nbsp;&nbsp; &nbsp; DWORD grfKeyState,</p>
        <p align=justify>&nbsp;&nbsp;&nbsp; &nbsp;POINTL pt, </p>
        <p align=justify>&nbsp;&nbsp; &nbsp;&nbsp; DWORD * pdwEffect&nbsp;&nbsp; )</p>
        </dir></dir></dir></font>
        <p align=justify>pDataobject </p>
        </strong><font lang=ZH-CN face=宋体>是从拖放的原数据中传递过来的一个</font>IDataObject<font lang=ZH-CN face=宋体>接口实例，包含数据对象的一些相关方法，可以通过此接口获得数据。</font><strong>
        <p align=justify>grfKeyState </p>
        </strong><font lang=ZH-CN face=宋体>为</font>DragEnter<font lang=ZH-CN face=宋体>被调用时当前的键盘和鼠标的状态，包含上面介绍过的键盘鼠标状态常数。</font><strong>
        <p align=justify>pt</p>
        </strong><font lang=ZH-CN face=宋体>表示鼠标所在的点。是以整个屏幕为参考坐标的。</font><strong>
        <p align=justify>pdwEffect</p>
        </strong><font lang=ZH-CN face=宋体>是</font>DoDragDrop<font lang=ZH-CN face=宋体>提供的一个</font>DWORD<font lang=ZH-CN face=宋体>指针，客户程序通过这个指针给</font>DoDragDrop<font lang=ZH-CN face=宋体>返回特定的状态。有效的状态包括：</font>
        <p align=justify>DROPEFFECT_NONE=0 <font lang=ZH-CN face=宋体>表示此窗口不能接受拖放。</font></p>
        <p align=justify>DROPEFFECT_MOVE=1 <font lang=ZH-CN face=宋体>表示拖放的结果将使源对象被删除</font></p>
        <p align=justify>DROPEFFECT_COPY=2 <font lang=ZH-CN face=宋体>表示拖放将引起源对象的复制。</font></p>
        <p align=justify>DROPEFFECT_LINK =4 <font lang=ZH-CN face=宋体>表示拖放源对象创建了一个对自己的连接</font></p>
        <p align=justify>DROPEFFECT_SCROLL=0x80000000<font lang=ZH-CN face=宋体>表示拖放目标窗口正在或将要进行卷滚。此标志可以和其他几个合用</font></p>
        <p align=justify>对于拖放对象来说，一般只要使用<strong><font face="宋体, MS Song">DROPEFFECT_NONE</font></strong><font lang=ZH-CN face=宋体>和</font><strong><font face="宋体, MS Song">DROPEFFECT_COPY</font></strong><font lang=ZH-CN face=宋体>即可。</font></p>
        <p align=justify>在<font face="宋体, MS Song">DragEnter</font><font lang=ZH-CN face=宋体>里要做什么呢？主要是告知拖放已经进入窗口区域，并判断是否支持某具体类型的拖放。</font></p>
        <p align=justify>首先<font face="宋体, MS Song">,</font><font lang=ZH-CN face=宋体>要判断键盘的状态。在调用</font><font face="宋体, MS Song">DragDropRegister</font><font lang=ZH-CN face=宋体>时我传入了一个</font><strong><font face="宋体, MS Song">AcceptKeyState</font></strong><font lang=ZH-CN face=宋体>并将其保存在</font><strong><font face="宋体, MS Song">m_AcceptKeyState</font></strong><font lang=ZH-CN face=宋体>成员变量里，现在可以拿它跟这里得到的</font><font face="宋体, MS Song">grfKeyState</font><font lang=ZH-CN face=宋体>比较：</font></p>
        <font color=#0000ff>
        <p align=justify>if(grfKeyState!=m_AcceptKeyState )</p>
        <p align=justify>{</p>
        <p align=justify>*pdwEffect = DROPEFFECT_NONE;</p>
        <p align=justify>return S_OK;</p>
        <p align=justify>}</p>
        </font><font lang=ZH-CN face=宋体>
        <p align=justify>如果键盘和鼠标的状态和我期望的不一样，那么</p>
        </font><font face="宋体, MS Song">pdwEffect</font><font lang=ZH-CN face=宋体>里返回</font><strong><font face="宋体, MS Song">DROPEFFECT_NONE</font></strong><font lang=ZH-CN face=宋体>表示不接受拖放。
        <p align=justify>然后</p>
        </font><font face="宋体, MS Song">,</font><font lang=ZH-CN face=宋体>判断拖放过来的</font><font face="宋体, MS Song">IDataObject</font><font lang=ZH-CN face=宋体>对象里有没有我感兴趣的数据。
        <p align=justify>这里要介绍的是两个关键的结构体</p>
        </font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>和</font><font face="宋体, MS Song">STDMEDIUM</font><strong>
        <p align=justify>FORMATETC</p>
        </strong><font lang=ZH-CN face=宋体>是</font>OLE<font lang=ZH-CN face=宋体>数据交换的一个关键结构，对某种设备，数据，和相关媒体做了格式上的描述。
        <p align=justify>其定义为</p>
        </font><font color=#0000ff>
        <p align=justify>typedef struct tagFORMATETC </p>
        <p align=justify>{ </p>
        <dir>
        <dir>
        <p align=justify>CLIPFORMAT cfFormat; </p>
        <p align=justify>DVTARGETDEVICE *ptd; </p>
        <p align=justify>DWORD dwAspect; </p>
        <p align=justify>LONG lindex; </p>
        <p align=justify>DWORD tymed; </p>
        </dir></dir></font><font lang=ZH-CN face=宋体 color=#0000ff>
        <p align=justify>}</p>
        </font><font color=#0000ff><font face="宋体, MS Song">FORMATETC, *LPFORMATETC;</font></font><font lang=ZH-CN face=宋体>
        <p align=justify>在这里我们最感兴趣的是</p>
        </font><strong><font face="宋体, MS Song">cfFormat</font></strong><font lang=ZH-CN face=宋体>和</font><strong><font face="宋体, MS Song">tymed</font></strong><font lang=ZH-CN face=宋体>两个数据。</font><strong><font face="宋体, MS Song">cfFormat</font></strong><font lang=ZH-CN face=宋体>是标准的&#8220;粘帖板&#8221;数据类型比如</font><strong><font face="宋体, MS Song">CF_TEXT</font></strong><font lang=ZH-CN face=宋体>之类。</font><font face="宋体, MS Song">tymed</font><font lang=ZH-CN face=宋体>表示数据所依附的媒介，比如内存，磁盘文件，存储对象等等。其他的成员可以参见</font><font face="宋体, MS Song">MSDN</font><font lang=ZH-CN face=宋体>。
        <p align=justify>一个典型的</p>
        </font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>结构变量定义如下：</font><strong>
        <p align=justify>FORMATETC cFmt = {(CLIPFORMAT) CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};</p>
        </strong>
        <p align=justify>IDataObject<font lang=ZH-CN face=宋体>提供了一个</font>GetData<font lang=ZH-CN face=宋体>接口来获取其实例里包含的数据，比如：</font></p>
        <font color=#0000ff>
        <p align=justify>STGMEDIUM stgMedium;</p>
        <p align=justify>ret = pDataObject-&gt;GetData(&amp;cFmt, &amp;stgMedium);</p>
        </font>
        <p align=justify>GetData<font lang=ZH-CN face=宋体>传入</font>cFmt<font lang=ZH-CN face=宋体>，以指出所感兴趣的数据，并将返回在</font><strong>stgMedium</strong><font lang=ZH-CN face=宋体>结构里。</font></p>
        <strong>
        <p align=justify>STGMEDIUM</p>
        </strong><font lang=ZH-CN face=宋体>的定义如下1</font><font color=#0000ff>
        <p align=justify>typedef struct tagSTGMEDIUM </p>
        <p align=justify>{ </p>
        <p align=justify>DWORD tymed; </p>
        <p align=justify>[switch_type(DWORD), switch_is((DWORD) tymed)] </p>
        <p align=justify>union { </p>
        <p align=justify>[case(TYMED_GDI)] HBITMAP hBitmap; </p>
        <p align=justify>[case(TYMED_MFPICT)] HMETAFILEPICT hMetaFilePict; </p>
        <p align=justify>[case(TYMED_ENHMF)] HENHMETAFILE hEnhMetaFile; </p>
        <p align=justify>[case(TYMED_HGLOBAL)] HGLOBAL hGlobal; </p>
        <p align=justify>[case(TYMED_FILE)] LPWSTR lpszFileName; </p>
        <p align=justify>[case(TYMED_ISTREAM)] IStream *pstm; </p>
        <p align=justify>[case(TYMED_ISTORAGE)] IStorage *pstg; </p>
        <p align=justify>[default] ; </p>
        <p align=justify>}; </p>
        <p align=justify>[unique] IUnknown *pUnkForRelease; </p>
        <p align=justify>}STGMEDIUM; </p>
        <p align=justify>typedef STGMEDIUM *LPSTGMEDIUM; </p>
        </font><font lang=ZH-CN face=宋体>
        <p align=justify>看起来颇为复杂，其实主要是一系列句柄或数据对象接口的联合，根据数据具体的类型，使用其中之一即可。</p>
        </font><font face="宋体, MS Song" color=#0000ff>tymed</font><font lang=ZH-CN face=宋体>和</font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>里一样，指出数据的载体类型（遗憾的是它不能指出具体的标准类型比如</font><font face="宋体, MS Song">CF_TEXT</font><font lang=ZH-CN face=宋体>或者其他）。至于</font><font face="宋体, MS Song" color=#0000ff>pUnkForRelease,</font><font lang=ZH-CN face=宋体>是源数据指定的一个接口，用来传递给</font><font face="宋体, MS Song">ReleaseStgMedium</font><font lang=ZH-CN face=宋体>函数，如果它不为</font><font face="宋体, MS Song">NULL</font><font lang=ZH-CN face=宋体>，则</font><font face="宋体, MS Song">ReleaseStgMedium</font><font lang=ZH-CN face=宋体>函数使用这个接口释放数据。如果为</font><font face="宋体, MS Song">NULL,</font><font lang=ZH-CN face=宋体>则</font><font face="宋体, MS Song">ReleaseStgMedium</font><font lang=ZH-CN face=宋体>函数使用默认的</font><font face="宋体, MS Song">IUnknown</font><font lang=ZH-CN face=宋体>接口。对于常规的拖放来说，这个对象指针应该为</font><font face="宋体, MS Song">NULL.</font><font lang=ZH-CN face=宋体>
        <p align=justify>得到了句柄或数据对象接口，也相当于得到了拖放的数据。</p>
        <p align=justify>定义一个特定的</p>
        </font><strong><font face="宋体, MS Song">FORMATETC</font></strong><font lang=ZH-CN face=宋体>结构实例传递给</font><font face="宋体, MS Song">IDataObject</font><font lang=ZH-CN face=宋体>的</font><font face="宋体, MS Song">GetData</font><font lang=ZH-CN face=宋体>，可以直接询问和获取某一种特定的数据。如果我们对我们想要的数据是非常确定的，这是比较有效率的方法。但是如果我们期望能够对拖放的对象进行自适应的话，我们可以采取枚举</font><font face="宋体, MS Song">IDataObject</font><font lang=ZH-CN face=宋体>里包含的所有数据类型的方案。这就要用到</font><strong><font face="宋体, MS Song"><font color=#0000ff>IEnumFORMATETC</font></font></strong><font lang=ZH-CN face=宋体>接口了。</font>
        <p align=justify>IEnumFORMATETC<font lang=ZH-CN face=宋体>接口从</font>IDataObject<font lang=ZH-CN face=宋体>接口里获取：</font></p>
        <dir>
        <dir><font color=#0000ff>
        <p align=justify>IEnumFormatETC *pEnumFmt = NULL;</p>
        <p align=justify>ret = pDataObject-&gt;EnumFormatEtc (DATADIR_GET,&amp;pEnumFmt);</p>
        </font></dir></dir><font lang=ZH-CN face=宋体>
        <p align=justify>如果获取成功，则可以通过</p>
        </font><font face="宋体, MS Song">IEnumFORMATETC</font><font lang=ZH-CN face=宋体>接口的</font><font face="宋体, MS Song">Next</font><font lang=ZH-CN face=宋体>方法，来枚举所有的数据格式：</font><font lang=ZH-CN face=宋体 color=#0000ff>
        <p align=justify>pEnumFmt-&gt;Reset (); </p>
        <p align=justify>HRESULT Ret=S_OK</p>
        <p align=justify>while(Ret!=S_OK)</p>
        <dir>
        <dir>
        <p align=justify>{</p>
        </dir></dir></font><font color=#0000ff>
        <p align=justify>Ret</p>
        </font><strong>=</strong><font color=#0000ff>pEnumFmt-&gt;Next(1,&amp;cFmt,&amp;Fetched);
        <p align=justify>if(SUCCEEDED(ret))</p>
        <p align=justify>if( cFmt.cfFormat == CF_TEXT</p>
        <p align=justify>||cFmt.cfFormat == CF_HDROP)</p>
        <p align=justify>{</p>
        <p align=justify></p>
        <p align=justify>if(GetDragData(pDataObject,cFmt)) </p>
        <p align=justify>EnterResult = true;</p>
        <p align=justify>}</p>
        <p align=justify>}</p>
        </font><font lang=ZH-CN face=宋体>
        <p align=justify>第一个参数表示一次获取的</p>
        </font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>结构数据的数量，</font><font face="宋体, MS Song">cFmt</font><font lang=ZH-CN face=宋体>是一个</font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>指针，指向一个数据缓冲，用来返回</font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>数据。</font><font face="宋体, MS Song">,Fetched</font><font lang=ZH-CN face=宋体>是</font><font face="宋体, MS Song">Next</font><font lang=ZH-CN face=宋体>调用后得到的</font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>数据个数。一般一次获取一个，直到Next返回不为S_OK。
        <p align=justify>我们可以对每个得到</p>
        </font><font face="宋体, MS Song">cFmt</font><font lang=ZH-CN face=宋体>调用</font><font face="宋体, MS Song">IDataObject-&gt;GetData</font><font lang=ZH-CN face=宋体>方法，但是一般来说，一个数据对象包含的数据不止一种，而且一般有一些自定义的数据类型（关于自定义数据类型，参见：</font><strong><font face="宋体, MS Song">RegisterClipboardFormat</font></strong><font lang=ZH-CN face=宋体>，如果要自己实现</font><font face="宋体, MS Song">Drag/Drop</font><font lang=ZH-CN face=宋体>源数据，这个函数是有用的），对此我们不感兴趣，因为这里只要求处理文本和文件的拖动，为此，只处理</font><font face="宋体, MS Song">cfFormat</font><font lang=ZH-CN face=宋体>为</font><font face="宋体, MS Song">CF_TEXT</font><font lang=ZH-CN face=宋体>和</font><font face="宋体, MS Song">CF_HROP</font><font lang=ZH-CN face=宋体>的数据：</font><strong>
        <p align=justify>GetDragData</p>
        </strong><font lang=ZH-CN face=宋体>为</font>CDropTargetEx<font lang=ZH-CN face=宋体>类的一个成员函数：</font><strong>
        <p align=justify>///////////////////////////////////////////////////</p>
        </strong><font color=#0000ff>
        <p align=justify>//Get The DragData from IDataObject ,save in HANDEL</p>
        <p align=justify>BOOL CDropTargetEx::GetDragData(IDataObject *pDataObject,FORMATETC cFmt)</p>
        <p align=justify>{</p>
        <p align=justify>HRESULT ret=S_OK;</p>
        <p align=justify>STGMEDIUM stgMedium;</p>
        <p align=justify>ret = pDataObject-&gt;GetData(&amp;cFmt, &amp;stgMedium);//GetData(CF_TEXT, &amp;stgMedium);</p>
        <p align=justify>if (FAILED(ret))</p>
        <p align=justify>{</p>
        <p align=justify>return FALSE;</p>
        <p align=justify>}</p>
        <p align=justify></p>
        <p align=justify>if (stgMedium.pUnkForRelease != NULL)</p>
        <p align=justify>{</p>
        <p align=justify>return FALSE;</p>
        <p align=justify>}</p>
        <p align=justify>///////////////////////////////////////////</p>
        <p align=justify>switch (stgMedium.tymed)</p>
        <p align=justify>{</p>
        <p align=justify>case TYMED_HGLOBAL:</p>
        <p align=justify>{</p>
        <p align=justify>LPDRAGDATA pData = new DRAGDATA;</p>
        <p align=justify>pData-&gt;cfFormat = cFmt.cfFormat ;</p>
        <p align=justify>memcpy(&amp;pData-&gt;stgMedium,&amp;stgMedium,sizeof(STGMEDIUM));</p>
        <p align=justify>m_Array.push_back(pData);</p>
        <p align=justify>return true;</p>
        <p align=justify>break;</p>
        <p align=justify>}</p>
        <p align=justify>default:</p>
        <p align=justify>// type not supported, so return error</p>
        <p align=justify>{</p>
        <p align=justify>::ReleaseStgMedium(&amp;stgMedium);</p>
        <p align=justify>}</p>
        <p align=justify>break;</p>
        <p align=justify>}</p>
        <p align=justify>return false;</p>
        <p align=justify>}</p>
        </font><font lang=ZH-CN face=宋体>
        <p align=justify>在这个成员函数里，根据</p>
        </font><font face="宋体, MS Song">cFmt</font><font lang=ZH-CN face=宋体>，调用</font><font face="宋体, MS Song">IDataObject-&gt;GetData</font><font lang=ZH-CN face=宋体>函数获得数据（对于</font><font face="宋体, MS Song">CF_TEXT</font><font lang=ZH-CN face=宋体>和</font><font face="宋体, MS Song">CF_HROP</font><font lang=ZH-CN face=宋体>来说，数据的媒介载体</font><font face="宋体, MS Song">tymed</font><font lang=ZH-CN face=宋体>都是</font><strong><font face="宋体, MS Song">HGLOBAL</font></strong><font lang=ZH-CN face=宋体>类型的）。
        <p align=justify>在具体实现的时候，我定义了一个结构：</p>
        </font><font color=#0000ff>
        <p align=justify>typedef struct _DRAGDATA</p>
        <p align=justify>{</p>
        <dir>
        <dir>
        <p align=justify>int cfFormat;</p>
        </dir></dir></font><font lang=ZH-CN face=宋体 color=#0000ff>
        <p align=justify></p>
        </font><font color=#0000ff><font face="宋体, MS Song">STGMEDIUM stgMedium;</font>
        <p align=justify>}DRAGDATA,*LPDRAGDATA;</p>
        </font><font lang=ZH-CN face=宋体>
        <p align=justify>　</p>
        <p align=justify>将</p>
        </font><strong><font face="宋体, MS Song">STGMEDIUM</font></strong><font lang=ZH-CN face=宋体>和数据类型（比如</font><font face="宋体, MS Song">CF_TEXT,</font><font lang=ZH-CN face=宋体>记录在</font><font face="宋体, MS Song">cfFormat</font><font lang=ZH-CN face=宋体>）都记录在DRAGDATA里。并且使用了一个</font><font face="宋体, MS Song">vector</font><font lang=ZH-CN face=宋体>数组，将这个结构保存在数组里。对于不是我们想要的</font><font face="宋体, MS Song">STGMEDIUM</font><font lang=ZH-CN face=宋体>数据，我们马上调用</font><font face="宋体, MS Song">ReleaseStgMedium</font><font lang=ZH-CN face=宋体>函数进行释放，免得造成内存泄露。
        <p align=justify>这样，</p>
        </font><font face="宋体, MS Song">DragEnter</font><font lang=ZH-CN face=宋体>的工作就基本完成了，最后需要做的就是给</font><font face="宋体, MS Song">DoDragDrop</font><font lang=ZH-CN face=宋体>返回相应的状态：如果我们获得了想要的数据就给</font><font face="宋体, MS Song">* pdwEffect</font><font lang=ZH-CN face=宋体>赋值为</font><strong><font face="宋体, MS Song">DROPEFFECT_COPY</font></strong><font lang=ZH-CN face=宋体>，否则，就是</font><strong><font face="宋体, MS Song">DROPEFFECT_NONE</font></strong><font lang=ZH-CN face=宋体>；
        <p align=justify>如果支持拖放，鼠标形状将变成一个有接受意义的图标，否则，是一个拒绝意义的图标。</p>
        </font><font lang=ZH-CN face=宋体 size=3>
        <p>&#160;</p>
        <hr>
        <p>&#160;</p>
        <ul></ul>
            </font><strong><font color=#ff0000 size=4>
            <p align=justify></p>
            <li>DragOver
            <p>&#160;</p>
            </font></strong><font lang=ZH-CN face=宋体>
            <p align=justify>鼠标拖动对象进入窗口之后，将会在窗口范围内移动，这时</p>
            </font><font face="宋体, MS Song">DoDragDrop</font><font lang=ZH-CN face=宋体>就会调用</font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>的</font><font face="宋体, MS Song">DragOver</font><font lang=ZH-CN face=宋体>接口。其原形为：</font><font color=#0000ff>
            <p align=justify>HRESULT DragOver(</p>
            <p align=justify>DWORD grfKeyState</p>
            <p align=justify>POINTL pt, </p>
            </font><font lang=ZH-CN face=宋体 color=#0000ff>
            <p align=justify></p>
            </font><font color=#0000ff><font face="宋体, MS Song">DWORD * pdwEffect </font></font><font lang=ZH-CN color=#0000ff>
            <p align=justify></p>
            </font><font color=#0000ff><font face="宋体, MS Song">)</font></font><font lang=ZH-CN face=宋体>
            <p align=justify>相对来说对于这个接口方法的实现可以简单的多：只要根据</p>
            </font><font face="宋体, MS Song">grfKeyState</font><font lang=ZH-CN face=宋体>判断键盘和鼠标的状态是否符合要求，根据</font><font face="宋体, MS Song">pt</font><font lang=ZH-CN face=宋体>传入的鼠标点判断该点是否支持拖放（比如将拖放区域限制在窗口的一部分的话），然后为</font><strong><font face="宋体, MS Song">*pdwEffect</font></strong><font lang=ZH-CN face=宋体>赋值为</font><strong><font face="宋体, MS Song">DROPEFFECT_COPY</font></strong><font lang=ZH-CN face=宋体>或</font><strong><font face="宋体, MS Song">DROPEFFECT_NONE.</font></strong><font lang=ZH-CN face=宋体>当然，还可以做一些你喜欢的事情，比如把鼠标坐标打印到屏幕上。不过为了性能和安全起见，建议不要做延时明显的操作。</font><font lang=ZH-CN face=宋体 size=3>
            <p>&#160;</p>
            <hr>
            <p>&#160;</p>
            <ul></ul>
                </font><strong><font color=#ff0000 size=4>
                <p align=justify></p>
                <li>DragLeave:
                <p>&#160;</p>
                </font></strong><font lang=ZH-CN face=宋体>
                <p align=justify>这个方法没有传入参数，相当简单。</p>
                <p>当拖动的鼠标离开了窗口区域，这个方法将被调用，你可以在这里写一些清理内存的代码。在</p>
                </font><font face="宋体, MS Song">CDropTargetEx</font><font lang=ZH-CN face=宋体>类里，由于在</font><font face="宋体, MS Song">DragEnter</font><font lang=ZH-CN face=宋体>里</font><font face="宋体, MS Song">new</font><font lang=ZH-CN face=宋体>了一些数据结构，并加到一个指针数组里，所以我必须在这里对此数据进行清理，对此结构里的</font><font face="宋体, MS Song">STDMEDIUM</font><font lang=ZH-CN face=宋体>调用</font><font face="宋体, MS Song">ReleaseStgMedium</font><font lang=ZH-CN face=宋体>然后</font><font face="宋体, MS Song">Delete</font><font lang=ZH-CN face=宋体>该结构。
                <p>另外，如果需要的话，可以通知用户鼠标指针已经离开了拖放区域。</p>
                </font><font lang=ZH-CN face=宋体 size=3>
                <p>&#160;</p>
                <hr>
                <p>&#160;</p>
                <ul></ul>
                    </font><strong><font color=#ff0000 size=4>
                    <li>Drop</font></strong><font lang=ZH-CN face=宋体>
                    <p>如果鼠标没有离开窗口，而是在窗口内释放按纽，那么拖放时间的&#8220;放&#8221;就在这时发生，</p>
                    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>接口的</font><font face="宋体, MS Song">Drop</font><font lang=ZH-CN face=宋体>方法被调用。其原形为</font><strong>
                    <p>HRESULT Drop(</p>
                    <p>IDataObject * pDataObject, </p>
                    <font lang=ZH-CN face=宋体>
                    <p>&#160;</p>
                    </font><font face="宋体, MS Song">DWORD grfKeyState, </font>
                    <p>POINTL pt, </p>
                    <font lang=ZH-CN face=宋体>
                    <p>&#160;</p>
                    </font><font face="宋体, MS Song">DWORD * pdwEffect </font><font lang=ZH-CN>
                    <p>&#160;</p>
                    </font><font face="宋体, MS Song">)</font></strong><font lang=ZH-CN face=宋体>
                    <p>有些资料建议在这里才调用</p>
                    </font><strong><font face="宋体, MS Song">pDataObject-&gt;GetData</font></strong><font lang=ZH-CN face=宋体>方法获取数据，在</font><font face="宋体, MS Song">CDropTargetEx</font><font lang=ZH-CN face=宋体>类里，数据实际上已经在</font><strong><font face="宋体, MS Song">DragEnter</font></strong><font lang=ZH-CN face=宋体>里获取了。这样做的理由是我希望一开始就获得数据，从它本身进行判断是否支持拖放</font><font face="宋体, MS Song">,</font><font lang=ZH-CN face=宋体>而不是在&#8220;放&#8221;的时候才判断是否合法数据。
                    <p>既然数据已经获得，那么我就可以从保存数据的指针数组里提取出</p>
                    </font><strong><font face="宋体, MS Song">STGMEDIUM</font></strong><font lang=ZH-CN face=宋体>数据来，并根据数据的具体格式进行处理（最后一定要记住对</font><font face="宋体, MS Song">STGMEDIUM</font><font lang=ZH-CN face=宋体>进行</font><strong><font face="宋体, MS Song">ReleaseStgMedium</font></strong><font lang=ZH-CN face=宋体>）
                    <p>对于</p>
                    </font><font face="宋体, MS Song">CF_TEXT</font><font lang=ZH-CN face=宋体>类型的数据，</font><font face="宋体, MS Song">STGMEDIUM</font><font lang=ZH-CN face=宋体>的成员</font><font face="宋体, MS Song">hGlobal</font><font lang=ZH-CN face=宋体>里包含的是一段全局内存数据。获取这些数据的方法是：
                    <dir>
                    <dir></dir></dir></font><font color=#0000ff>
                    <p>TCHAR *pBuff = NULL;</p>
                    <p>pBuff=(LPSTR)GlobalLock(hText);</p>
                    <p>GlobalUnlock(hText);</p>
                    </font><font lang=ZH-CN face=宋体>
                    <p>则得到一个指向内存数据的指针pBuff。在我这个例子里一般是一段</p>
                    </font><font face="宋体, MS Song">"\0"</font><font lang=ZH-CN face=宋体>结尾的文本字符串。这样就实现了文本的拖放。
                    <p>对于</p>
                    </font><font face="宋体, MS Song">CF_HDROP</font><font lang=ZH-CN face=宋体>类型的数据，</font><font face="宋体, MS Song">STGMEDIUM</font><font lang=ZH-CN face=宋体>成员</font><font face="宋体, MS Song">hGlobal</font><font lang=ZH-CN face=宋体>是一个</font><font face="宋体, MS Song">HDROP</font><font lang=ZH-CN face=宋体>类型的句柄。通过这个句柄，可以获得拖放的文件列表。如：</font><font color=#0000ff>
                    <p>BOOL CDropTargetEx::ProcessDrop(HDROP hDrop)</p>
                    <p>{</p>
                    <p>UINT iFiles,ich =0;</p>
                    <p>TCHAR Buffer[MAX_PATH]="";</p>
                    <p>memset(&amp;iFiles,0xff,sizeof(iFiles));</p>
                    <dir>
                    <dir>
                    <p>int Count = ::DragQueryFile(hDrop,iFiles,Buffer,0); //Get the Drag _Files Number.</p>
                    </dir></dir></font><font lang=ZH-CN face=宋体 color=#0000ff>
                    <p>&#160;</p>
                    </font><font color=#0000ff><font face="宋体, MS Song">if(Count)</font>
                    <p>for (int i=0;i&lt;Count;i++)</p>
                    <p>{</p>
                    <p>if(::DragQueryFile(hDrop,i,Buffer,sizeof(Buffer)))</p>
                    <p>{</p>
                    <dir>
                    <dir>
                    <dir>
                    <dir>
                    <dir>
                    <dir>
                    <dir>
                    <dir>
                    <p>//Got the FileName in Buffer</p>
                    </dir></dir></dir></dir></dir></dir></dir></dir></font><font lang=ZH-CN face=宋体 color=#0000ff>
                    <p>}</p>
                    <p>}</p>
                    <p>&#160;</p>
                    </font><font color=#0000ff><font face="宋体, MS Song">::DragFinish(hDrop);</font>
                    <dir>
                    <dir>
                    <p>return true; </p>
                    </dir></dir></font><font lang=ZH-CN face=宋体 color=#0000ff>
                    <p>}</p>
                    </font><font lang=ZH-CN face=宋体>
                    <p>获得的</p>
                    </font><font face="宋体, MS Song">Buffer</font><font lang=ZH-CN face=宋体>是就是拖放的文件名，如果拖放的是多个文件，在</font><font face="宋体, MS Song">for</font><font lang=ZH-CN face=宋体>循环里可以依次获取这些文件的文件名。这样就实现了文件的拖放。</font><font lang=ZH-CN face=宋体 size=3>
                    <p>&#160;</p>
                    <hr>
                    <p>&#160;</p>
                    </font><font lang=ZH-CN face=宋体>
                    <p align=justify>　</p>
                    </font><strong>
                    <p align=justify>CDropTargetEx</p>
                    </strong><font lang=ZH-CN face=宋体>类使用非常简单:
                    <p align=justify>在客户窗口的相关文件中，定义一个</p>
                    </font><font face="宋体, MS Song">CDropTargetEx</font><font lang=ZH-CN face=宋体>实例：</font><strong><font face="宋体, MS Song">CDropTargetEx DropTarget;</font></strong><font lang=ZH-CN face=宋体>
                    <p align=justify>在窗口创建之后，将窗口句柄进行拖放注册： </p>
                    </font><strong>
                    <p align=justify>DropTarget.DragDropRegister(hWnd);</p>
                    </strong><font lang=ZH-CN face=宋体>
                    <p align=justify>或者 </p>
                    </font><strong>
                    <p align=justify>DropTarget.DragDropRegister(hWnd<font lang=ZH-CN face=宋体>，</font>MK_CONTROL|MK_LBUTTON);</p>
                    </strong><font lang=ZH-CN face=宋体>
                    <p align=justify>表示鼠标左键按下并且按住</p>
                    </font><font face="宋体, MS Song">Ctrl</font><font lang=ZH-CN face=宋体>键的拖放有效</font><font face="宋体, MS Song">;</font><font lang=ZH-CN face=宋体>
                    <p align=justify>对于获取拖放的结果，我使用的是回调函数方式：</p>
                    <p align=justify>回调原形</p>
                    </font><strong><font face="宋体, MS Song">typedef VOID (_stdcall *DROPCALLBACK)(LPCSTR Buffer,int type);</font></strong><font lang=ZH-CN face=宋体>
                    <p align=justify>在适当的地方（比如窗口的实现</p>
                    </font><font face="宋体, MS Song">CPP</font><font lang=ZH-CN face=宋体>里）定义函数</font><font face="宋体, MS Song">DropCallback</font><font lang=ZH-CN face=宋体>：</font><strong>
                    <p align=justify>void _stdcall DropCallBack(LPCSTR Buffer,int type)</p>
                    </strong><font lang=ZH-CN face=宋体>
                    <p align=justify>并且将其地址赋于</p>
                    </font><font face="宋体, MS Song">DropTarget</font><font lang=ZH-CN face=宋体>实例：</font><strong>
                    <p align=justify>DropTarget.SetCallBack(DropCallBack);</p>
                    </strong><font lang=ZH-CN face=宋体>
                    <p align=justify>这样，拖放文本到客户窗口，回调函数将被调用，参数</p>
                    </font><strong><font face="宋体, MS Song">Buffer</font></strong><font lang=ZH-CN face=宋体>为拖放的文本，</font><strong><font face="宋体, MS Song">format</font></strong><font lang=ZH-CN face=宋体>为</font><font face="宋体, MS Song">CF_TEXT</font><font lang=ZH-CN face=宋体>。而拖放文件的时候，对每个被拖放的文件都调用一次回调函数，参数</font><strong><font face="宋体, MS Song">Buffer</font></strong><font lang=ZH-CN face=宋体>为文件全路径名，</font><strong><font face="宋体, MS Song">format</font></strong><font lang=ZH-CN face=宋体>为</font><strong><font face="宋体, MS Song">CF_HDROP</font></strong><font lang=ZH-CN face=宋体>。
                    <p align=justify>示例的</p>
                    </font><font face="宋体, MS Song">DropCallBack</font><font lang=ZH-CN face=宋体>代码为：</font><font color=#0000ff>
                    <p align=justify>void _stdcall DropCallBack(LPCSTR Buffer,int format)</p>
                    <p align=justify>{</p>
                    <p align=justify>switch(format)</p>
                    <p align=justify>{</p>
                    <p align=justify>case CF_TEXT:</p>
                    <p align=justify>{</p>
                    <p align=justify>SetWindowText(hEdit,Buffer);</p>
                    <p align=justify>break;</p>
                    <p align=justify>}</p>
                    <p align=justify>case CF_HDROP:</p>
                    <p align=justify>{</p>
                    <p align=justify>TCHAR Buf[2048]="";</p>
                    <p align=justify>sprintf(Buf,"File : &lt;%s&gt; is Drag and Drop to this Windows ,Open it?",Buffer);</p>
                    <p align=justify>if(MessageBox(hMainWnd,Buf,"Question",MB_YESNO)==IDYES)</p>
                    <p align=justify>{</p>
                    <p align=justify>ShellExecute(0,"open",Buffer,"","",SW_SHOW);</p>
                    <p align=justify>}</p>
                    <p align=justify>}</p>
                    <p align=justify>default:</p>
                    <dir>
                    <dir>
                    <dir>
                    <dir>
                    <p align=justify>break;</p>
                    </dir></dir></dir></dir></font><font lang=ZH-CN face=宋体 color=#0000ff>
                    <p align=justify>}</p>
                    <p align=justify>}</p>
                    </font><font lang=ZH-CN face=宋体>
                    <p align=justify>　</p>
                    <strong>
                    <p align=justify>总结</p>
                    </strong>：使用</font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>实现通用的拖放，只要实现其</font><font face="宋体, MS Song">7</font><font lang=ZH-CN face=宋体>个接口，并且对得到的</font><font face="宋体, MS Song">IDataObject</font><font lang=ZH-CN face=宋体>用正确的格式（</font><font face="宋体, MS Song">FORMATETC</font><font lang=ZH-CN face=宋体>）调用正确的</font><font face="宋体, MS Song">GetData</font><font lang=ZH-CN face=宋体>获取数据，返回</font><strong><font face="宋体, MS Song">DROPEFFECT</font></strong><font lang=ZH-CN face=宋体>决定拖放的特征和结果，并处理拖放结果即可。
                    <p align=justify>要注意的小问题是：</p>
                    <ul>
                        <p align=justify></p>
                        <li>要调用<strong>OleInitialize</strong>而不是CoInitialize或CoInitializeEx对COM进行初始，否则<strong>RegisterDragDrop</strong>将不会成功，返回的错误是E_OUTOFMEMORY--内存不够，无法进行该操作。
                        <p>&#160;</p>
                        <p align=justify></p>
                        <li>调用ReleaseStgMedium释放STGMEDIUM里的数据，而不是直接对其hGlobal成员调用CloseHandle.
                        <p>&#160;</p>
                        <p align=justify></p>
                        <li>拖放操作关系到两个进程的数据交换，会将两个进程都堵塞，直到拖放完成为止，所以，在接管拖放的接口方法中，不要进行过于耗时的运算。
                        <p>&#160;</p>
                        </li>
                    </ul>
                    <p align=justify>这个例子相当简单，还可以简化，比如取消</p>
                    </font><font face="宋体, MS Song">vector,</font><font lang=ZH-CN face=宋体>将获得</font><font face="宋体, MS Song">HGLOBAL</font><font lang=ZH-CN face=宋体>句柄作为成员变量存储，或者将获取数据的操作全部放到</font><font face="宋体, MS Song">Drop</font><font lang=ZH-CN face=宋体>方法里。
                    <p align=justify>对于拖放文件，还有一个更简单的方法：响应</p>
                    </font><font face="宋体, MS Song"><strong>WM_DROPFILES</strong></font><font lang=ZH-CN face=宋体>消息。步骤是：
                    <ul>
                        <p align=justify></p>
                        <li>对客户窗口调用</li>
                    </ul>
                    </font><font face="宋体, MS Song"><strong>DropAccepFiles</strong>,</font><font lang=ZH-CN face=宋体>使该窗口可以接受文件拖放。
                    <p>&#160;</p>
                    <p align=justify></p>
                    <li>响应</font><font face="宋体, MS Song">WM_DROPFILES</font><font lang=ZH-CN face=宋体>消息，其</font><font face="宋体, MS Song">wParam</font><font lang=ZH-CN face=宋体>就是</font><font face="宋体, MS Song">HDROP</font><font lang=ZH-CN face=宋体>句柄
                    <p>&#160;</p>
                    <p align=justify></p>
                    <li>对此句柄调用</font><font face="宋体, MS Song">DropQueryFiles</font><font lang=ZH-CN face=宋体>获取拖放文件列表并结束拖放，参见上面关于</font><strong><font face="宋体, MS Song">ProcessDrop</font></strong><font lang=ZH-CN face=宋体>的代码
                    <p>&#160;</p>
                    <p align=justify>对于拖放的全面阐述，请参见</p>
                    </font><strong><font face="宋体, MS Song">MSDN-&gt;PlatformSDK Document-&gt;User Interface Services-&gt;Windows Shell</font></strong><font lang=ZH-CN face=宋体>里关于<strong>&#8220;</strong></font><font face="宋体, MS Song">Transferring Shell Objects with Drag-and-Drop and the Clipboard</font><font lang=ZH-CN face=宋体>&#8221;一章。</font><font face="宋体, MS Song">Windows Shell</font><font lang=ZH-CN face=宋体>系统提供了很多接口，让用户利用和扩充这些接口，很方便的开发和使用丰富的</font><font face="宋体, MS Song">shell</font><font lang=ZH-CN face=宋体>服务，确实是一种很聪明的设计。
                    <dir>
                    <p align=justify>　</p>
                    <p align=justify></p>
                    </dir><strong>
                    <p align=justify>附</p>
                    </strong></font><a href="http://www.mapinfo.com.cn/upload/downfile.asp?fileid=61"><strong><u><font lang=ZH-CN face=宋体 color=#0000ff size=3>例子和代码</font></u></strong></a> </li>
<img src ="http://www.cppblog.com/andxie99/aggbug/19228.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-03-05 12:52 <a href="http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>存储过程开发模板</title><link>http://www.cppblog.com/andxie99/archive/2007/02/25/18966.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 25 Feb 2007 06:58:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/02/25/18966.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/18966.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/02/25/18966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/18966.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/18966.html</trackback:ping><description><![CDATA[总结的一个存储过程开发模板，主要是避免一些常见问题。<br>书写规范为：SQL关键字均使用小写。但是定义连接属性，如SET NOCOUNT ON可以用大写；变量采用Camel风格，单词首字符大写。<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_0_557_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_557_Open_Text.style.display='none'; Codehighlighter1_0_557_Closed_Image.style.display='inline'; Codehighlighter1_0_557_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_0_557_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_557_Closed_Text.style.display='none'; Codehighlighter1_0_557_Open_Image.style.display='inline'; Codehighlighter1_0_557_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span id=Codehighlighter1_0_557_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_0_557_Open_Text><span style="COLOR: #008080">/*</span><span style="COLOR: #008080">*********************************************<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>作者：&nbsp;&nbsp;&nbsp;&nbsp;XXX<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>创建日期：YYYY-MM-DD<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>功能描述：（清楚、详尽。如：本存储过程主要用于生成主键ID，<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp; 为了适应分布式数据库的应用，采用SiteID（三位）+YYYYMMDD（八位）+顺序位（八位）组成BigInt类型编码。）<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>-----------------------------------------------<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>修改者：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>修改日期：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>修改描述：（如：本次修改加入了对存储过程的错误捕获。）<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>-----------------------------------------------<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>传入参数：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@X1<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据类型：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;描述：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@X2<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据类型：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;描述：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>传出参数：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@X1<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据类型：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;描述：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>返回值：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@XX<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据类型：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;描述：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>*********************************************</span><span style="COLOR: #008080">*/</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;先检查存储过程是否存在，如果存在，先drop掉</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">Object_Id</span><span style="COLOR: #000000">(N</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">[dbo].[P_xxxx]</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">,&nbsp;N</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">P</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">not</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">drop</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">procedure</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">dbo</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #000000">.</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">P_xxxx</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">go</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">create</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">procedure</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">dbo</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #000000">.</span><span style="COLOR: #ff0000">[</span><span style="COLOR: #ff0000">P_xxxx</span><span style="COLOR: #ff0000">]</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">&nbsp;DataType,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">@xxx2</span><span style="COLOR: #000000">&nbsp;DataType&nbsp;output<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;出于性能考虑，这是每个存储过程的第一条语句</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;当SET&nbsp;NOCOUNT为ON时，将不向客户端发送存储过程中每个语句的DONE_IN_PROC消息。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- 如果存储过程中包含的一些语句并不返回许多实际数据，则该设置由于大量减少了网络流量，因此可显著提高性能。</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">SET</span><span style="COLOR: #000000">&nbsp;NOCOUNT&nbsp;</span><span style="COLOR: #0000ff">ON</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;定义错误变量，为raiserror使用</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">declare</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@ErrorMessage</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">nvarchar</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">4000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">declare</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@ErrorSeverity</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">int</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">declare</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@ErrorState</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">int</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;注释：</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;1、为方便调试，在存储过程内部一律使用&#8220;--&#8221;代替&#8220;/*&nbsp;*/&#8221;</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;2、每个关键性操作请在前面注释</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;变量定义：</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;1、不要在循环中定义变量</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;2、如果变量是用于存储某个字段的值，请使变量类型（包括精度）和字段类型一致</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;3、最好显示的为变量初始化</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;变量赋值：</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;使用set&nbsp;@xxx&nbsp;=&nbsp;?，不要用早期版本的select&nbsp;@xxx&nbsp;=&nbsp;?方式</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;从SQL中为变量赋值采用</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">select</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;col1,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">@xxx2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;col2<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;tabelname<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;一次性清空表，请使用truncate代替delete</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">truncate</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">table</span><span style="COLOR: #000000">&nbsp;tablename<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;insert语句要把字段名写全</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">insert</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">into</span><span style="COLOR: #000000">&nbsp;tablename(col1,&nbsp;col2&#8230;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">values</span><span style="COLOR: #000000">(</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #008000">@xxx2</span><span style="COLOR: #000000">&#8230;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;批量插入</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">insert</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">into</span><span style="COLOR: #000000">&nbsp;tablename1(col1,&nbsp;col2&#8230;)&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">select</span><span style="COLOR: #000000">&nbsp;col1,&nbsp;col2&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;tablename2<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;判断语句</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;?&nbsp;</span><span style="COLOR: #808080">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@xxx2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;?)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;循环语句</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">&lt;&gt;</span><span style="COLOR: #000000">&nbsp;?)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;游标：</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;尽量避免使用游标</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;定义游标</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">declare</span><span style="COLOR: #000000">&nbsp;cursor_xxx&nbsp;</span><span style="COLOR: #0000ff">cursor</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">select</span><span style="COLOR: #000000">&nbsp;col1,&nbsp;col2&nbsp;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;tablename<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">where</span><span style="COLOR: #000000">&nbsp;col1&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@xxx</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;打开游标</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">open</span><span style="COLOR: #000000">&nbsp;cursor_xxx;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;将游标中的值取到变量中</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">fetch</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">next</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;cursor_xxx<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">into</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #008000">@xxx2</span><span style="COLOR: #000000">&nbsp;&#8230;;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;开始游标循环</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="FONT-WEIGHT: bold; COLOR: #008000">@@fetch_status</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">0</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">fetch</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">next</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;cursor_xxx<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">into</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@xxx1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #008000">@xxx2</span><span style="COLOR: #000000">&nbsp;&#8230;;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;结束游标</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">close</span><span style="COLOR: #000000">&nbsp;cursor_xxx;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;销毁游标</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">deallocate</span><span style="COLOR: #000000">&nbsp;cursor_xxx;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;事务</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;如果显式使用事务，请注意SQL&nbsp;Server默认的事务隔离级别是读提交（Read&nbsp;Committed）</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;如果使用更高级别的事务隔离级别，请详细阅读帮助文档，避免不必要的锁阻塞</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">tran</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">update</span><span style="COLOR: #000000">&nbsp;&#8230;&#8230;;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">commit</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">&nbsp;异常处理机制</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;1、在第一次使用异常处理机制之前声明异常变量</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;2、对容易发生错误的操作，用try<img src="http://www.cppblog.com/Images/dot.gif">catch进行异常捕获（声明变量不需要）</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;3、在清理资源后，将错误记录保存在ExecProcdure_ErrorLog表中</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;ExecProcdure_ErrorLog建表脚本如下：</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;create&nbsp;table&nbsp;dbo.ExecProcdure_ErrorLog(</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ID]&nbsp;[bigint]&nbsp;identity(1,&nbsp;1)&nbsp;not&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorNumber]&nbsp;[int]&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorSeverity]&nbsp;[int]&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorState]&nbsp;[int]&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorProcedure]&nbsp;[nvarchar](200)&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorLine]&nbsp;[nvarchar](50)&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorMessage]&nbsp;[nvarchar](4000)&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;[ErrorDateTime]&nbsp;[datetime]&nbsp;null,</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;constraint&nbsp;[PK_ExecProcdure_ErrorLog]&nbsp;primary&nbsp;key&nbsp;clustered</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;([ID]&nbsp;asc&nbsp;)&nbsp;</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;with&nbsp;(IGNORE_DUP_KEY&nbsp;=&nbsp;OFF)&nbsp;ON&nbsp;[primary]</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">----&nbsp;)&nbsp;ON&nbsp;(primary]</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;4、最后使用raiserror将错误返回给调用者</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;错误处理例子</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000">&nbsp;try<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000">&nbsp;try<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;begin&nbsp;catch&nbsp;要紧跟着end&nbsp;try，中间不允许有其他语句</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000">&nbsp;catch<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;清理上面try中使用的资源，如删除临时表、销毁游标、回滚事务等</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;设置错误变量</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@ErrorMessage</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;ERROR_mESSAGE(),<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@ErrorSeverity</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;ERROR_SEVERITY(),<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@ErrorState</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;ERROR_STATE();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;返回错误信息</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">raiserror</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #008000">@ErrorMessage</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">@ErrorSeverity</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">@ErrorState</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">--&nbsp;保存错误信息</span><span style="COLOR: #008080"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">insert</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">into</span><span style="COLOR: #000000">&nbsp;ExecProcdure_ErrorLog<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ErrorNumber,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorSeverity,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorState,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorProcedure,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorLine,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorMessage,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorDateTime)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">select</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ERROR_NUMBER()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorNumber,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ERROR_SEVERITY()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorSeverity,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ERROR_STATE()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorState,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ERROR_PROCEDURE()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorProcedure,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ERROR_LINE()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorLine,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ERROR_MESSAGE()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorMessage,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #ff00ff">getdate</span><span style="COLOR: #000000">()&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;ErrorDateTime;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000">&nbsp;catch<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">end</span></div>
<img src ="http://www.cppblog.com/andxie99/aggbug/18966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-02-25 14:58 <a href="http://www.cppblog.com/andxie99/archive/2007/02/25/18966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常用的DOS网络命令</title><link>http://www.cppblog.com/andxie99/archive/2007/01/07/17400.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 07 Jan 2007 11:00:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/01/07/17400.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/17400.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/01/07/17400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/17400.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/17400.html</trackback:ping><description><![CDATA[<p><strong>ping<br></strong>&nbsp;&nbsp;&nbsp; ping是个使用频率极高的实用程序，用于确定本地主机是否能与另一台主机交换（发送与接收）数据报。根据返回的信息，你就可以推断TCP/IP参数是否设置得正确以及运行是否正常。需要注意的是：成功地与另一台主机进行一次或两次数据报交换并不表示TCP/IP配置就是正确的，我们必须执行大量的本地主机与远程主机的数据报交换，才能确信TCP/IP的正确性。<br>简单的说，Ping就是一个测试程序，如果Ping运行正确，你大体上就可以排除网络访问层、网卡、MODEM的输入输出线路、电缆和路由器等存在的故障，从而减小了问题的范围。但由于可以自定义所发数据报的大小及无休止的高速发送，Ping也被某些别有用心的人作为DDOS（拒绝服务攻击）的工具，前段时间Yahoo就是被黑客利用数百台可以高速接入互联网的电脑连续发送大量Ping数据报而瘫痪的。 </p>
<p>按照缺省设置，Windows上运行的Ping命令发送4个ICMP（网间控制报文协议）回送请求，每个32字节数据，如果一切正常，你应能得到4个回送应答。 </p>
<p>Ping能够以毫秒为单位显示发送回送请求到返回回送应答之间的时间量。如果应答时间短，表示数据报不必通过太多的路由器或网络连接速度比较快。Ping还能显示TTL（Time To Live存在时间）值，你可以通过TTL值推算一下数据包已经通过了多少个路由器：源地点TTL起始值（就是比返回TTL略大的一个2的乘方数）-返回时TTL值。例如，返回TTL值为119，那么可以推算数据报离开源地址的TTL起始值为128，而源地点到目标地点要通过9个路由器网段（128-119）；如果返回TTL值为246，TTL起始值就是256，源地点到目标地点要通过9个路由器网段。 </p>
<p>通过Ping检测网络故障的典型次序 </p>
<p>正常情况下，当你使用Ping命令来查找问题所在或检验网络运行情况时，你需要使用许多Ping命令，如果所有都运行正确，你就可以相信基本的连通性和配置参数没有问题；如果某些Ping命令出现运行故障，它也可以指明到何处去查找问题。下面就给出一个典型的检测次序及对应的可能故障： </p>
<p>ping 127.0.0.1——这个Ping命令被送到本地计算机的IP软件，该命令永不退出该计算机。如果没有做到这一点，就表示TCP/IP的安装或运行存在某些最基本的问题。 </p>
<p>ping 本机IP——这个命令被送到你计算机所配置的IP地址，你的计算机始终都应该对该Ping命令作出应答，如果没有，则表示本地配置或安装存在问题。出现此问题时，局域网用户请断开网络电缆，然后重新发送该命令。如果网线断开后本命令正确，则表示另一台计算机可能配置了相同的IP地址。</p>
<p>ping 局域网内其他IP——这个命令应该离开你的计算机，经过网卡及网络电缆到达其他计算机，再返回。收到回送应答表明本地网络中的网卡和载体运行正确。但如果收到0个回送应答，那么表示子网掩码（进行子网分割时，将IP地址的网络部分与主机部分分开的代码）不正确或网卡配置错误或电缆系统有问题。 </p>
<p>ping 网关IP——这个命令如果应答正确，表示局域网中的网关路由器正在运行并能够作出应答。 </p>
<p>ping 远程IP——如果收到4个应答，表示成功的使用了缺省网关。对于拨号上网用户则表示能够成功的访问Internet（但不排除ISP的DNS会有问题）。 </p>
<p>ping localhost——localhost是个操作系统的网络保留名，它是127.0.0.1的别名，每台计算机都应该能够将该名字转换成该地址。如果没有做到这一带内，则表示主机文件（/Windows/host）中存在问题。</p>
<p>ping <a href="http://www.yahoo.com/">www.yahoo.com</a>——对这个域名执行Ping命令，你的计算机必须先将域名转换成IP地址，通常是通过DNS服务器。如果这里出现故障，则表示DNS服务器的IP地址配置不正确或DNS服务器有故障（对于拨号上网用户，某些ISP已经不需要设置DNS服务器了）。顺便说一句：你也可以利用该命令实现域名对IP地址的转换功能。 </p>
<p>如果上面所列出的所有Ping命令都能正常运行，那么你对你的计算机进行本地和远程通信的功能基本上就可以放心了。但是，这些命令的成功并不表示你所有的网络配置都没有问题，例如，某些子网掩码错误就可能无法用这些方法检测到。 </p>
<p>Ping命令的常用参数选项 </p>
<p><br>　　-t 表示将不间断向目标IP发送数据包，直到我们强迫其停止（Ctrl+C）。试想，如果你使用100M的宽带接入，而目标IP是56K的小猫，那么要不了多久，目标IP就因为承受不了这么多的数据而掉线，呵呵，一次攻击就这么简单的实现了。 　　 </p>
<p>　　-l 定义发送数据包的大小，默认为32字节，我们利用它可以最大定义到65500字节。结合上面介绍的-t参数一起使用，会有更好的效果。 　　 </p>
<p>　　-n 定义向目标IP发送数据包的次数，默认为3次。如果网络速度比较慢，3次对我们来说也浪费了不少时间，因为现在我们的目的仅仅是判断目标IP是否存在，那么就定义为一次吧。 　　 </p>
<p>　　说明一下，如果-t 参数和 -n参数一起使用，ping命令就以放在后面的参数为标准，比如&#8220;ping IP -t -n 3&#8221;，虽然使用了-t参数，但并不是一直ping下去，而是只ping 3次。另外，ping命令不一定非得ping IP，也可以直接ping主机域名，这样就可以得到主机的IP。 　　 </p>
<p>　　从TTL的返回值可以初步判断被ping主机的操作系统，之所以说&#8220;初步判断&#8221;是因为这个值是可以修改的。这里TTL=32表示操作系统可能是win98。 <br>　　（小知识：如果TTL=128，则表示目标主机可能是Win2000；如果TTL=250，则目标主机可能是Unix） </p>
<p><br><strong>Netstat</strong> </p>
<p>Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据，一般用于检验本机各端口的网络连接情况。 </p>
<p>&nbsp;&nbsp;&nbsp; 如果你的计算机有时候接受到的数据报会导致出错数据删除或故障，你不必感到奇怪，TCP/IP可以容许这些类型的错误，并能够自动重发数据报。但如果累计的出错情况数目占到所接收的IP数据报相当大的百分比，或者它的数目正迅速增加，那么你就应该使用Netstat查一查为什么会出现这些情况了。 </p>
<p>Netstat的一些常用选项： </p>
<p>&nbsp;&nbsp;&nbsp; 这是一个用来查看网络状态的命令，操作简便功能强大。 　　 </p>
<p>netstat -s——本选项能够按照各个协议分别显示其统计数据。如果你的应用程序（如Web浏览器）运行速度比较慢，或者不能显示Web页之类的数据，那么你就可以用本选项来查看一下所显示的信息。你需要仔细查看统计数据的各行，找到出错的关键字，进而确定问题所在。 </p>
<p>netstat -e——本选项用于显示关于以太网的统计数据。它列出的项目包括传送的数据报的总字节数、错误数、删除数、数据报的数量和广播的数量。这些统计数据既有发送的数据报数量，也有接收的数据报数量。这个选项可以用来统计一些基本的网络流量。 </p>
<p>netstat -r——本选项可以显示关于路由表的信息，类似于后面所讲使用route print命令时看到的信息。除了显示有效路由外，还显示当前有效的连接。告诉我们机器的网关、子网掩码等信息。</p>
<p>netstat -a——本选项显示一个所有的有效连接信息列表，即查看所有开放端口，包括已建立的连接（ESTABLISHED），也包括监听连接请求（LISTENING）的那些连接。可以有效发现和预防木马，可以知道机器所开的服务等信息。</p>
<p>netstat -n——显示所有已建立的有效连接。 </p>
<p>Netstat的妙用 </p>
<p>经常上网的人一般都使用ICQ的，不知道你有没有被一些讨厌的人骚扰得不敢上线，想投诉却又不知从何下手？其实，你只要知道对方的IP，就可以向他所属的ISP投诉了。但怎样才能通过ICQ知道对方的IP呢？如果对方在设置ICQ时选择了不显示IP地址，那你是无法在信息栏中看到的。其实，你只需要通过Netstat就可以很方便的做到这一点：当他通过ICQ或其他的工具与你相连时（例如你给他发一条ICQ信息或他给你发一条信息），你立刻在DOS Prompt下输入netstat -n或netstat -a就可以看到对方上网时所用的IP或ISP域名了。甚至连所用Port都完全暴露了，如果你想给他一些教训，这些信息已经足够&#8230;&#8230; </p>
<p><br><strong>IPConfig</strong> </p>
<p>IPConfig实用程序和它的等价图形用户界面——Windows 95/98中的WinIPCfg可用于显示当前的TCP/IP配置的设置值。这些信息一般用来检验人工配置的TCP/IP设置是否正确。但是，如果你的计算机和所在的局域网使用了动态主机配置协议（Dynamic Host Configuration Protocol，DHCP——Windows NT下的一种把较少的IP地址分配给较多主机使用的协议，类似于拨号上网的动态IP分配），这个程序所显示的信息也许更加实用。这时，IPConfig可以让你了解你的计算机是否成功的租用到一个IP地址，如果租用到则可以了解它目前分配到的是什么地址。了解计算机当前的IP地址、子网掩码和缺省网关实际上是进行测试和故障分析的必要项目。 </p>
<p>最常用的选项： </p>
<p>ipconfig——当使用IPConfig时不带任何参数选项，那么它为每个已经配置了的接口显示IP地址、子网掩码和缺省网关值。 </p>
<p>ipconfig /all——当使用all选项时，IPConfig能为DNS和WINS服务器显示它已配置且所要使用的附加信息（如IP地址等），并且显示内置于本地网卡中的物理地址（MAC）。如果IP地址是从DHCP服务器租用的，IPConfig将显示DHCP服务器的IP地址和租用地址预计失效的日期（有关DHCP服务器的相关内容请详见其他有关NT服务器的书籍或询问你的网管），其输出信息见图6的下半部分。 </p>
<p>ipconfig /release和ipconfig /renew——这是两个附加选项，只能在向DHCP服务器租用其IP地址的计算机上起作用。如果你输入ipconfig /release，那么所有接口的租用IP地址便重新交付给DHCP服务器（归还IP地址）。如果你输入ipconfig /renew，那么本地计算机便设法与DHCP服务器取得联系，并租用一个IP地址。请注意，大多数情况下网卡将被重新赋予和以前所赋予的相同的IP地址。 </p>
<p>如果你使用的是Windows 95/98，那么你应该更习惯使用winipcfg而不是ipconfig，因为它是一个图形用户界面，而且所显示的信息与ipconfig相同，并且也提供发布和更新动态IP地址的选项（见图7，全部详细资料见图8）。如果你购买了Windows NT Resource Kit（NT资源包），那么Windows NT也包含了一个图形替代界面，该实用程序的名字是wntipcfg，和Windows 95/98的winipcfg类似。 </p>
<p><strong>ARP（地址转换协议）</strong> </p>
<p>ARP是一个重要的TCP/IP协议，并且用于确定对应IP地址的网卡物理地址。实用arp命令，你能够查看本地计算机或另一台计算机的ARP高速缓存中的当前内容。此外，使用arp命令，也可以用人工方式输入静态的网卡物理/IP地址对，你可能会使用这种方式为缺省网关和本地服务器等常用主机进行这项操作，有助于减少网络上的信息量。 </p>
<p>按照缺省设置，ARP高速缓存中的项目是动态的，每当发送一个指定地点的数据报且高速缓存中不存在当前项目时，ARP便会自动添加该项目。一旦高速缓存的项目被输入，它们就已经开始走向失效状态。例如，在Windows NT网络中，如果输入项目后不进一步使用，物理/IP地址对就会在2至10分钟内失效。因此，如果ARP高速缓存中项目很少或根本没有时，请不要奇怪，通过另一台计算机或路由器的ping命令即可添加。所以，需要通过arp命令查看高速缓存中的内容时，请最好先ping 此台计算机（不能是本机发送ping命令）。 </p>
<p>常用命令选项： </p>
<p>arp -a或arp -g——用于查看高速缓存中的所有项目。-a和-g参数的结果是一样的，多年来-g一直是UNIX平台上用来显示ARP高速缓存中所有项目的选项，而Windows用的是arp -a（-a可被视为all，即全部的意思），但它也可以接受比较传统的-g选项。 </p>
<p>arp -a IP——如果你有多个网卡，那么使用arp -a加上接口的IP地址，就可以只显示与该接口相关的ARP缓存项目。 </p>
<p>arp -s IP 物理地址——你可以向ARP高速缓存中人工输入一个静态项目。该项目在计算机引导过程中将保持有效状态，或者在出现错误时，人工配置的物理地址将自动更新该项目。 </p>
<p>arp -d IP——使用本命令能够人工删除一个静态项目。 </p>
<p><strong>Tracert </strong></p>
<p>当数据报从你的计算机经过多个网关传送到目的地时，Tracert命令可以用来跟踪数据报使用的路由（路径）。该实用程序跟踪的路径是源计算机到目的地的一条路径，不能保证或认为数据报总遵循这个路径。如果你的配置使用DNS，那么你常常会从所产生的应答中得到城市、地址和常见通信公司的名字。Tracert是一个运行得比较慢的命令（如果你指定的目标地址比较远），每个路由器你大约需要给它15秒钟。 </p>
<p>Tracert的使用很简单，只需要在tracert后面跟一个IP地址或URL，Tracert会进行相应的域名转换的。Tracert一般用来检测故障的位置，你可以用tracert IP在哪个环节上出了问题，虽然还是没有确定是什么问题，但它已经告诉了我们问题所在的地方，你也就可以很有把握的告诉别人——某某出了问题。 </p>
<p><br><strong>Route</strong> </p>
<p>大多数主机一般都是驻留在只连接一台路由器的网段上。由于只有一台路由器，因此不存在使用哪一台路由器将数据报发表到远程计算机上去的问题，该路由器的IP地址可作为该网段上所有计算机的缺省网关来输入。 </p>
<p>但是，当网络上拥有两个或多个路由器时，你就不一定想只依赖缺省网关了。实际上你可能想让你的某些远程IP地址通过某个特定的路由器来传递，而其他的远程IP则通过另一个路由器来传递。 </p>
<p>在这种情况下，你需要相应的路由信息，这些信息储存在路由表中，每个主机和每个路由器都配有自己独一无二的路由表。大多数路由器使用专门的路由协议来交换和动态更新路由器之间的路由表。但在有些情况下，必须人工将项目添加到路由器和主机上的路由表中。Route就是用来显示、人工添加和修改路由表项目的。 </p>
<p>一般使用选项： </p>
<p>route print——本命令用于显示路由表中的当前项目，在单路由器网段上的输出结果如图12，由于用IP地址配置了网卡，因此所有的这些项目都是自动添加的。 </p>
<p>route add——使用本命令，可以将信路由项目添加给路由表。例如，如果要设定一个到目的网络209.98.32.33的路由，其间要经过5个路由器网段，首先要经过本地网络上的一个路由器，器IP为202.96.123.5，子网掩码为255.255.255.224，那么你应该输入以下命令： </p>
<p>route add 209.98.32.33 mask 255.255.255.224 202.96.123.5 metric 5 </p>
<p>route change——你可以使用本命令来修改数据的传输路由，不过，你不能使用本命令来改变数据的目的地。下面这个例子可以将数据的路由改到另一个路由器，它采用一条包含3个网段的更直的路径： </p>
<p>route add 209.98.32.33 mask 255.255.255.224 202.96.123.250 metric 3 </p>
<p>route delete——使用本命令可以从路由表中删除路由。例如：route delete 209.98.32.33 </p>
<p><br><strong>NBTStat</strong> </p>
<p>&nbsp;&nbsp;&nbsp; 该命令使用TCP/IP上的NetBIOS显示协议统计和当前TCP/IP连接，使用这个命令你可以得到远程主机的NETBIOS信息，比如用户名、所属的工作组、网卡的MAC地址等。在此我们就有必要了解几个基本的参数。 　　 　 </p>
<p>　　当得到了对方的IP或者机器名的时候，就可以使用nbtstat命令来进一步得到对方的信息了，这又增加了我们入侵的保险系数。 </p>
<p>常用选项： </p>
<p>nbtstat -n——列出本地机器的NETBIOS信息（显示寄存在本地的名字和服务程序）。 </p>
<p>nbtstat -c——本命令用于显示NetBIOS名字高速缓存的内容。NetBIOS名字高速缓存用于寸放与本计算机最近进行通信的其他计算机的NetBIOS名字和IP地址对。 </p>
<p>nbtstat -r——本命令用于清除和重新加载NetBIOS名字高速缓存。 </p>
<p>nbtstat -a IP——通过IP显示另一台计算机的物理地址和名字列表，你所显示的内容就像对方计算机自己运行nbtstat -n一样。 </p>
<p>nbtstat -s IP——显示实用其IP地址的另一台计算机的NetBIOS连接表。 </p>
<p><br><strong>Net</strong> </p>
<p>&nbsp;&nbsp;&nbsp; 这个命令是网络命令中最重要的一个，必须透彻掌握它的每一个子命令的用法，因为它的功能实在是太强大了，这简直就是微软为我们提供的最好的入侵工具。首先让我们来看一看它都有那些子命令，键入net /?回车。 </p>
<p>　　在这里，我们重点掌握几个入侵常用的子命令。 　　 </p>
<p>　　net view 　　 </p>
<p>　　使用此命令查看远程主机的所以共享资源。命令格式为net view <a href="file://IP/">\\IP</a>。</p>
<p>　　net use </p>
<p>　　把远程主机的某个共享资源影射为本地盘符，图形界面方便使用，呵呵。命令格式为net use x: <a href="file://IP/sharename">\\IP\sharename</a>。下面表示和192.168.0.7建立IPC$连接（net use <a href="file://IP/IPC$">\\IP\IPC$</a> "password" /user:"name"）， 　　 </p>
<p>　　建立了IPC$连接后，呵呵，就可以上传文件了：copy nc.exe <a href="file://192.168.0.7/admin$">\\192.168.0.7\admin$</a>，表示把本地目录下的nc.exe传到远程主机，结合后面要介绍到的其他DOS命令就可以实现入侵了。 　　 </p>
<p>　　net start </p>
<p>　　使用它来启动远程主机上的服务。当你和远程主机建立连接后，如果发现它的什么服务没有启动，而你又想利用此服务怎么办？就使用这个命令来启动吧。用法：net start servername，如启动telnet服务等。 　　 </p>
<p>　　net stop </p>
<p>　　入侵后发现远程主机的某个服务碍手碍脚，怎么办？利用这个命令停掉就ok了，用法和net start同。 　　 </p>
<p>　　net user </p>
<p>　　查看和帐户有关的情况，包括新建帐户、删除帐户、查看特定帐户、激活帐户、帐户禁用等。这对我们入侵是很有利的，最重要的，它为我们克隆帐户提供了前提。键入不带参数的net user，可以查看所有用户，包括已经禁用的。下面分别讲解。 </p>
<p>　　1，net user abcd 1234 /add，新建一个用户名为abcd，密码为1234的帐户，默认为user组成员。 </p>
<p>　　2，net user abcd /del，将用户名为abcd的用户删除。 </p>
<p>　　3，net user abcd /active:no，将用户名为abcd的用户禁用。 </p>
<p>　　4，net user abcd /active:yes，激活用户名为abcd的用户。 </p>
<p>　　5，net user abcd，查看用户名为abcd的用户的情况　　 </p>
<p>　　net localgroup </p>
<p>　　查看所有和用户组有关的信息和进行相关操作。键入不带参数的net localgroup即列出当前所有的用户组。在入侵过程中，我们一般利用它来把某个帐户提升为administrator组帐户，这样我们利用这个帐户就可以控制整个远程主机了。用法：net localgroup groupname username /add。</p>
<p>　　net time </p>
<p>　　这个命令可以查看远程主机当前的时间。如果你的目标只是进入到远程主机里面，那么也许就用不到这个命令了。但简单的入侵成功了，难道只是看看吗？我们需要进一步渗透。这就连远程主机当前的时间都需要知道，因为利用时间和其他手段可以实现某个命令和程序的定时启动，为我们进一步入侵打好基础。用法：net time <a href="file://IP/">\\IP</a>。 　　 </p>
<p><strong>at</strong> </p>
<p>　　这个命令的作用是安排在特定日期或时间执行某个特定的命令和程序（知道net time的重要了吧？）。当我们知道了远程主机的当前时间，就可以利用此命令让其在以后的某个时间（比如2分钟后）执行某个程序和命令。用法：at time command <a href="file://computer/">\\computer</a>。 　　 </p>
<p>ftp 　　 </p>
<p>　　大家对这个命令应该比较熟悉了吧？网络上开放的ftp的主机很多，其中很大一部分是匿名的，也就是说任何人都可以登陆上去。现在如果你扫到了一台开放ftp服务的主机（一般都是开了21端口的机器），如果你还不会使用ftp的命令怎么办？下面就给出基本的ftp命令使用方法。 </p>
<p>　　首先在命令行键入ftp回车，出现ftp的提示符，这时候可以键入&#8220;help&#8221;来查看帮助（任何DOS命令都可以使用此方法查看其帮助)。 　　 </p>
<p>　　大家可能看到了，这么多命令该怎么用？其实也用不到那么多，掌握几个基本的就够了。 　　 </p>
<p>　　首先是登陆过程，这就要用到open了，直接在ftp的提示符下输入&#8220;open 主机IP ftp端口&#8221;回车即可，一般端口默认都是21，可以不写。接着就是输入合法的用户名和密码进行登陆了，这里以匿名ftp为例介绍。 　　 </p>
<p>　　用户名和密码都是ftp，密码是不显示的。当提示**** logged in时，就说明登陆成功。这里因为是匿名登陆，所以用户显示为Anonymous。 　　 </p>
<p>　　接下来就要介绍具体命令的使用方法了。 　　 </p>
<p>　　dir 跟DOS命令一样，用于查看服务器的文件，直接敲上dir回车，就可以看到此ftp服务器上的文件。 </p>
<p>　　cd 进入某个文件夹。 </p>
<p>　　get 下载文件到本地机器。 </p>
<p>　　put 上传文件到远程服务器。这就要看远程ftp服务器是否给了你可写的权限了，如果可以，呵呵，该怎么 利用就不多说了，大家就自由发挥去吧。 </p>
<p>　　delete 删除远程ftp服务器上的文件。这也必须保证你有可写的权限。 </p>
<p>　　bye 退出当前连接。 </p>
<p>　　quit 同上。 <br>　　 </p>
<p><strong>telnet </strong></p>
<p>　　功能强大的远程登陆命令，几乎所有的入侵者都喜欢用它，屡试不爽。为什么？它操作简单，如同使用自己的机器一样，只要你熟悉DOS命令，在成功以administrator身份连接了远程机器后，就可以用它来做想干的一切了。下面介绍一下使用方法，首先键入telnet回车，再键入help查看其帮助信息。 　　 </p>
<p>　　然后在提示符下键入open IP回车，这时就出现了登陆窗口，让你输入合法的用户名和密码，这里输入任何密码都是不显示的。 　　 </p>
<p>　　当输入用户名和密码都正确后就成功建立了telnet连接，这时候你就在远程主机上具有了和此用户一样的权限，利用DOS命令就可以实现你想干的事情了。这里我使用的超级管理员权限登陆的。　　&nbsp; </p>
<p>　　另外大家应该清楚，任何人要想进入系统，必须得有一个合法的用户名和密码（输入法漏洞差不多绝迹了吧），哪怕你拿到帐户的只有一个很小的权限，你也可以利用它来达到最后的目的。所以坚决消灭空口令，给自己的帐户加上一个强壮的密码，是最好的防御弱口令入侵的方法</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/17400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-01-07 19:00 <a href="http://www.cppblog.com/andxie99/archive/2007/01/07/17400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2007-1-7周计划</title><link>http://www.cppblog.com/andxie99/archive/2007/01/07/17387.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 07 Jan 2007 06:02:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/01/07/17387.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/17387.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/01/07/17387.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/17387.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/17387.html</trackback:ping><description><![CDATA[    工作上，上周末刚被调到另一个项目组救火，估计这周工作轻松不了，业余时间的学习计划也就订灵活点，复习一下数据结构和算法方面的知识，每种结构写一个Demo：<br />    线性表<br />    数组<br />    矩阵<br />        特殊矩阵<br />        稀疏矩阵<br />    堆栈<br />    队列<br />    跳表和散列<br />    树<br />    二叉树<br />    准备在接下来的一周复习一下树的常用应用（优先队列、二叉搜索树、AVL树、红-黑树、B-树等）。再花一周学习一下图。然后就是算法了。<br />    计划订得不具体，大概是因为业余时间，不确定因素太多，如（工作、自己懒惰等等），但自己有个习惯，每天睡前会把当天所做的事情用十多个字记在台历的日期旁边的空白处。看着密密麻麻的小台历，比起如今流行的每年一次的“阅之有字，言之无物”的工作总结，心里透着一种踏实。真希望每天一个目标，睡前问问自己“否达到了自己定下的目标”。<br /><img src ="http://www.cppblog.com/andxie99/aggbug/17387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-01-07 14:02 <a href="http://www.cppblog.com/andxie99/archive/2007/01/07/17387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>35岁前成功的12条黄金法则</title><link>http://www.cppblog.com/andxie99/archive/2006/12/29/16965.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Fri, 29 Dec 2006 01:55:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/12/29/16965.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/16965.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/12/29/16965.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/16965.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/16965.html</trackback:ping><description><![CDATA[抄一篇鼓鼓劲。<br>原文地址：<a href="http://www.javaresearch.org/article/60374.htm">http://www.javaresearch.org/article/60374.htm</a><br><br>第一章：一个目标<br><br>　　一艘没有航行目标的船，任何方向的风都是逆风<br><br>　　1、你为什么是穷人，第一点就是你没有立下成为富人的目标<br><br>　　2、你的人生核心目标是什么？<br><br>　　杰出人士与平庸之辈的根本差别并不是天赋、机遇，而在于有无目标。<br><br>　　3、起跑领先一步，人生领先一大步：成功从选定目标开始<br><br>　　4、贾金斯式的人永远不会成功<br><br>　　为什么大多数人没有成功？真正能完成自己计划的人只有5%，大多数人不是将自己的目标舍弃，就是沦为缺乏行动的空想<br><br>　　5、如果你想在35岁以前成功，你一定在25至30岁之间确立好你的人生目标<br><br>　　6、每日、每月、每年都要问自己：我是否达到了自己定下的目标<br><br>　　第二章：两个成功基点<br><br>　　站好位置，调正心态，努力冲刺，35岁以前成功<br><br>　　（一）人生定位<br><br>　　1、人怕入错行：你的核心竞争力是什么？<br><br>　　2、成功者找方法，失败者找借口<br><br>　　3、从三百六十行中选择你的最爱<br><br>　　人人都可以创业，但却不是人人都能创业成功<br><br>　　4、寻找自己的黄金宝地<br><br>　　（二）永恒的真理：心态决定命运，35岁以前的心态决定你一生的命运<br><br>　　1、不满现状的人才能成为富翁<br><br>　　2、敢于梦想，勇于梦想，这个世界永远属于追梦的人<br><br>　　3、35岁以前不要怕，35岁以后不要悔<br><br>　　4、出身贫民，并非一辈子是贫民，只要你永远保持那颗进取的心。中国成功人士大多来自小地方<br><br>　　5、做一个积极的思维者<br><br>　　6、不要败给悲观的自己<br><br>　　有的人比你富有一千倍，他们也会比你聪明一千倍么？不会，他们只是年轻时心气比你高一千倍。<br><br>　　人生的好多次失败，最后并不是败给别人，而是败给了悲观的自己。<br><br>　　7、成功者不过是爬起来比倒下去多一次<br><br>　　8、宁可去碰壁，也不要在家里面壁<br><br>　　克服你的失败、消极的心态<br><br>　　（1）找个地方喝点酒<br><br>　　（2）找个迪厅跳跳舞<br><br>　　（3）找帮朋友侃侃山<br><br>　　（4）积极行动起来<br><br>　　第三章：三大技巧<br><br>　　1、管理时间：你的时间在哪里，你的成就就在哪里。<br><br>　　把一小时看成60分钟的人，比看作一小时的人多60倍<br><br>　　2、你不理财，财不理你<br><br>　　3、自我管理，游刃有余<br><br>　　（1）创业不怕本小，脑子一定要好<br><br>　　（2）可以开家特色店<br><br>　　（3）做别人不愿做的生意<br><br>　　第四章：四项安身立命的理念<br><br>　　35岁以前一定要形成个人风格<br><br>　　1、做人优于做事<br><br>　　做事失败可以重来，做人失败却不能重来<br><br>　　（1）做人要讲义气<br><br>　　（2）永不气馁<br><br>　　2、豁达的男人有财运，豁达的女人有帮夫运<br><br>　　35岁以前搞定婚姻生活<br><br>　　3、忠诚的原则：35岁以前你还没有建立起忠诚美誉，这一缺点将要困扰你的一生<br><br>　　4、把小事做细，但不要耍小聪明<br><br>　　中国人想做大事的人太多，而愿把小事做完美的人太少<br><br>　　第五章：五分运气<br><br>　　比尔?盖茨说：人生是不公平的，习惯去接受它吧<br><br>　　1、人生的确有很多运气的成人：谋事在人，成事在天：中国的古训说明各占一半<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;2、机会时常意外地降临，但属于那些不应决不放弃的人<br><br>　　3、抓住人生的每一次机会<br><br>　　机会就像一只小鸟，如果你不抓住，它就会飞得无影无踪<br><br>　　4、者早一步，愚者晚一步<br><br>　　第六章：六项要求<br><br>　　1、智慧<br><br>　　（1）别人可你以拿走你的一切，但拿不走你的智慧<br><br>　　（2）巧妙运用自己的智慧<br><br>　　（3）智者与愚者的区别&nbsp;<br><br>2、勇气<br><br>　　（1）勇气的力量有时会让你成为超人<br><br>　　（2）敢于放弃，敢于舍得<br><br>　　3、培养自己的领导才能、领袖气质<br><br>　　（1）激情感染别人<br><br>　　（2）三o七法则实现领袖气质<br><br>　　（3）拍板决断能力<br><br>　　（4）人格魅力<br><br>　　4、创造性：不要做循规蹈矩的人<br><br>　　25-35岁是人生最有创造性的阶段，很多成功人士也都产生在这一阶段<br><br>　　5、明智<br><br>　　（1）知道自己的长处、短处，定向聚焦<br><br>　　（2）尽量在自己的熟悉的领域努力<br><br>　　6、持之以恒的行动力：在你选定行业坚持十年<br>
<img src ="http://www.cppblog.com/andxie99/aggbug/16965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-12-29 09:55 <a href="http://www.cppblog.com/andxie99/archive/2006/12/29/16965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2006-12-24周计划</title><link>http://www.cppblog.com/andxie99/archive/2006/12/24/16808.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 24 Dec 2006 15:24:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/12/24/16808.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/16808.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/12/24/16808.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/16808.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/16808.html</trackback:ping><description><![CDATA[
		<p>    上周没有完成学习计划，不过感觉还是收获不少，至少对汇编有一些实质上的了解，照着练习做了一些汇编的小程序。<br />    这周因周六接了一个以前单位的物流方向的小软件，准备用C++和Access实现，已经开始了，争取元旦前能出V0.1(b)版，最迟用元旦的假期完成。好久没用MFC了，熟悉熟悉未必不是好事。<br />    这周公司要开年会，估计得出去两天，学习计划大概都得改风险管理了。把主要时间花在完成物流软件上吧，每天有时间读读英语，就当休息。</p>
		<p>    又记了篇流水帐，只是想让自己养成一个习惯，每天自己有个总结，每周有个小计划。</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/16808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-12-24 23:24 <a href="http://www.cppblog.com/andxie99/archive/2006/12/24/16808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows环境下32位汇编语言程序设计（第2版）学习笔记1_第一章 背景知识</title><link>http://www.cppblog.com/andxie99/archive/2006/12/21/16687.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Thu, 21 Dec 2006 05:07:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/12/21/16687.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/16687.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/12/21/16687.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/16687.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/16687.html</trackback:ping><description><![CDATA[
		<p>第 1 章 背景知识<br />1.1 Win32的软硬件平台<br />1.2 Windows的特色<br />1.3 必须了解的东西<br />1.3.1 80x86处理器的工作模式<br />    80386处理器有3种工作模式：实模式、保护模式和虚拟86模式。<br />    保护模式是80386处理器的主要工作模式。在此方式下，80386可以寻址4 GB的地址空间，同时，保护模式提供了8038的多任务、内存分页管理和优先级保护等机制。<br />    虚拟86模式是为了在保护模式下提供和8086处理器的兼容，在虚拟86模式下，同样支持任务切换、内存分页管理和优先级，但内存的寻址方式和8086相同，也是可以寻址1MB的空间。<br />    1. 实模式<br />    80386处理器被复位或加电的时候以实模式启动。80386处理器在实模式下的存储器寻址方式和8086是一样的，由段寄存器的内容乘以16当做基地址，加上段内的偏移地址形成最终的物理地址，这时候它的32位地址线只使用了低20位。在实模式下，80386处理器不能对内存进行分页管理，所以指令寻址的地址就是内存中实际的物理地址。在实模式下，所有的段都是可以读、写和执行的。实模式下80386不支持优先级，所有的指令相当于工作在特权级（优先级0），所以它可以执行所有特权指令。<br />    2. 保护模式<br />    当80386工作在保护模式下的时候，它的所有功能都是可用的。这时80386所有的32根地址线都可供寻址，物理寻址空间高达4 GB。在保护模式下，支持内存分页机制，提供了对虚拟内存的良好支持。在保护模式下，80386处理器还支持优先级机制。优先级分4个级别（0级～3级），操作系统运行在最高的优先级0上，应用程序则运行在比较低的级别上。<br />    DOS操作系统运行于实模式下，而Windows操作系统运行于保护模式下。<br />    3. 虚拟86模式<br />    虚拟86模式是为了在保护模式下执行8086程序而设置的。虽然80386处理器已经提供了实模式来兼容8086程序，但这时8086程序实际上只是运行得快了一点，对CPU的资源还是独占的。虚拟86模式是以任务形式在保护模式上执行的，在80386上可以同时支持由多个真正的80386任务和虚拟86模式构成的任务。在虚拟86模式下，80386支持任务切换和内存分页。在Windows操作系统中，有一部分程序专门用来管理虚拟86模式的任务，称为虚拟86管理程序。为了和8086程序的寻址方式兼容，虚拟86模式采用和8086一样的寻址方式，即用段寄存器乘以16当做基址再配合偏移地址形成线性地址，寻址空间为1 MB。但显然多个虚拟86任务不能同时使用同一位置的1 MB地址空间，否则会引起冲突。操作系统利用分页机制将不同虚拟86任务的地址空间映射到不同的物理地址上去，这样每个虚拟86任务看起来都认为自己在使用0～1 MB的地址空间。<br />1.3.2 Windows的内存管理<br />    1. DOS操作系统的内存安排<br />    DOS操作系统运行于实模式中，由于8086处理器的寻址范围只有1 MB，当时系统硬件使用的存储器地址被安排在高端，地址是从A0000h（即640 KB）开始的384 KB中，其中有用于显示的视频缓冲区和BIOS的地址空间。而在内存低端，安排了中断向量表和BIOS数据区；剩下从500h开始到A0000h总共不到640 KB的内存是操作系统和应用程序所能够使用的；应用程序不可能使用这640 KB以外的内存。这就是著名的“640KB限制”。<br /></p>
		<div align="center">
				<img height="276" alt="DOS Memory.JPG" src="http://www.cppblog.com/images/cppblog_com/andxie99/DOS%20Memory.JPG" width="275" border="0" />
		</div>
		<br />    2. 80386的内存寻址机制<br />    因为80386所有的通用寄存器都是32位的，232相当于4G，所以用任何一个通用寄存器来间接寻址，不必分段就已经可以访问到所有的内存地址。这是不是说，在保护模式下，段寄存器就不再有用了呢？答案是否定的。虽然在寻址上不再有分段的限制问题，但在保护模式下，一个地址空间是否可以被写入，可以被多少优先级的代码写入，是不是允许执行等涉及保护的问题就出来了。要解决这些问题，必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途。但是涉及属性和保护模式下段的其他参数，要表示的信息太多了，要用64位长的数据才能表示。我们把这64位的属性数据叫做段描述符（Segment Descriptor）。把所有段的段描述符顺序放在内存中的指定位置，组成一个段描述符表（Descriptor Table）；而段寄存器中的16位用来做索引信息，指定这个段的属性用段描述符表中的第几个描述符来表示。这时，段寄存器中的信息不再是段地址了，而是段选择器（Segment Selector）。可以通过它在段描述符表中“选择”一个项目以得到段的全部信息。<br />    80386中引入了两个新的寄存器来管理段描述符表。一个是48位的全局描述符表寄存器GDTR，一个是16位的局部描述符表寄存器LDTR。GDTR指向的描述符表为全局描述符表GDT（Global Descriptor Table）。它包含系统中所有任务都可用的段描述符，通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述符及各任务的LDT段等；全局描述符表只有一个。<br />    LDTR则指向局部描述符表LDT（Local Descriptor Table）。80386处理器设计成每个任务都有一个独立的LDT。它包含有每个任务私有的代码段、数据段和堆栈段的描述符，也包含该任务所使用的一些门描述符，如任务门和调用门描述符等。<br />    3. 80386的内存分页机制<br />    80386处理器把4 KB大小的一块内存当做一“页”内存，每页物理内存可以根据“页目录”和“页表”，随意映射到不同的线性地址上。这样，就可以将物理地址不连续的内存的映射连到一起，在线性地址上视为连续。页表可以指定一个页面并不真正映射到物理内存中。这样，访问这个页的指令会引发页异常错误。这时，处理器会自动转移到页异常处理程序中去。操作系统可以在异常处理程序中将硬盘上的虚拟内存读到内存中并修改页表重新映射，然后重新执行引发异常的指令。这样指令可以正常执行下去。<br />    4. Windows的内存安排<br />    如果把虚拟内存暂时先视为物理内存的一部分，从物理内存的层次看，Windows操作系统和DOS一样，也是所有的内容共享内存。但是从应用程序代码的层次看，也就是说从分页映射后线性地址的层次看，内存的安排却不是这个样子。因为Windows是一个分时的多任务操作系统，CPU时间被分成一个个的时间片后分配给不同程序轮流使用，在一个程序的时间片中，和这个程序执行无关的东西（如其他程序的代码和数据）并不需要映射到线性地址中去。在物理内存中，操作系统和系统DLL的代码需要供每个应用程序调用，所以在所有的时间片中都必须被映射；用户程序只在自己所属的时间片内被映射；而用户DLL则有选择地被映射。假设程序A和程序C都要用到xxx.dll，那么物理内存中xxx.dll的代码在图中的时间片1和n中被映射，其他的时间片就不需要映射，当然，物理内存中只需要一份xxx.dll的代码。<br />    ● 每个应用程序都有自己的4 GB的寻址空间。该空间可存放操作系统、系统DLL和用户DLL的代码，它们之中有各种函数供应用程序调用。再除去其他的一些空间，余下的是应用程序的代码、数据和可以分配的地址空间。<br />    ● 不同应用程序的线性地址空间是隔离的。虽然它们在物理内存中同时存在，但在某个程序所属的时间片中，其他应用程序的代码和数据没有被映射到可寻址的线性地址中，所以是不可访问的。从编程的角度看，程序可以使用4 GB的寻址空间，而且这个空间是“私有”的。<br />    ● DLL程序没有自己“私有”的空间。它们总是被映射到其他应用程序的地址空间中，当做其他应用程序的一部分运行。原因很简单，如果它不和其他程序同属一个地址空间，应用程序该如何调用它呢？<br />    5. 从Win32汇编的角度看内存寻址<br />    Win32汇编中的内存访问为用户程序的代码段、数据段和堆栈段全部预定义好了段描述符。这些段的起始地址为0，限长为ffffffff，所以用它们可以直接寻址全部的4 GB地址空间。程序开始执行的时候，CS，DS，ES和SS都已经指向了正确的描述符，在整个程序的生命周期内，程序员不必改动这些段寄存器，也不必关心它们的值究竟是多少（实际上是想改也改不了）。<br />    1.3.3 Windows的特权保护<br />    1. 80386的中断和异常<br />    8086或80386实模式下中断和异常的处理过程：实模式下的中断和异常服务程序地址存放在中断向量表中。中断向量表位于物理内存00000h开始的400h字节中，共支持100h个中断向量；每个中断向量是一个xxxx:yyyy格式的地址，占用4字节。当发生n号异常或n号中断，或者执行到int n指令的时候，CPU首先到内存n×4的地方取出服务程序的地址aaaa:bbbb；然后将标志寄存器、中断时的CS和IP压入堆栈，接着转移到aaaa:bbbb处执行；在服务程序最后遇到iret的时候，CPU从堆栈中恢复标志寄存器，然后取出CS和IP并返回。<br />    在保护模式下，中断或异常处理往往从用户代码切换到操作系统代码中执行。由于保护模式下的代码有优先级之分，为了使高优先级的代码能够安全地被低优先级的代码调用，保护模式下增加了“门”的概念。“门”指向某个优先级高的程序所规定的入口点，所有优先级低的程序调用优先级高的程序只能通过门重定向，进入门所规定的入口点。保护模式下的中断和异常等服务程序也要从“门”进入，80386的门分为中断门、自陷门和任务门几种。<br />    在保护模式下要表示一个中断或异常服务程序的信息需要用8个字节，包括门的种类以及xxxx:yyyyyyyy格式的入口地址等。这组信息叫做“中断描述符”。保护模式下把所有的中断描述符放在一起组成“中断描述符表”IDT（Interrupt Descriptor Table）。IDT不再放在固定的地址00000h处，而是采用可编程设置的方式，支持的中断数量也可以设置。为此80386处理器引入了一个新的48位寄存器IDTR。IDTR的高32位指定了IDT在内存中的基址（线性地址），低16位指定了IDT的长度，相当于指定了可以支持的中断数量。<br />    2. 80386的保护机制<br />    保护机制主要由下列几方面组成：<br />    ● 段的类型检查——段的类型是由段描述符指定的，主要属性有是否可执行，是否可读和是否可写等。而CS，DS和SS等段选择器是否能装入某种类型的段描述符是有限制的。如不可执行的段不能装入CS；不可读的段不能装入DS与ES等数据段寄存器；不可写的段不能装入SS等。如果段类型检查通不过，则处理器会产生一般性保护异常或堆栈异常。<br />    ● 页的类型检查——除了可以在段级别上指定整个段是否可读写外，在页表中也可以为每个页指定是否可写。对于特权级下的执行代码，所有的页都是可写的。但对于1，2和3级的代码，还要根据页表中的R/W项决定是否可写，企图对只读的页进行写操作会产生页异常。<br />    ● 访问数据时的级别检查——优先级低的代码不能访问优先级高的数据段。80386的段描述符中有一个DPL域（描述符优先级），表示这个段可以被访问的最低优先级。而段选择器中含有RPL域（请求优先级），表示当前执行代码的优先级。只有DPL在数值上大于或等于RPL值的时候，该段才是可以访问的，否则会产生一般性保护异常。<br />    ● 控制转移的检查——在处理器中，有很多指令可以实现控制转移，如jmp，call，ret，int和iret等指令。但优先级低的代码不能随意转移到优先级高的代码中，所以遇到这些指令的时候，处理器要检查转移的目的位置是否合法。<br />    ● 指令集的检查——有两类指令可以影响保护机制。第一类是改变GDT，LDT，IDT以及控制寄存器等关键寄存器的指令，称为特权指令；第二类是操作I/O端口的指令以及cli和sti等改变中断允许的指令，称为敏感指令。试想一下，如果用户级程序可以用sti禁止一切中断（包括时钟中断），那么整个系统就无法正常运行，所以这些指令的运行要受到限制。特权指令只能在优先级0上才能运行，而敏感指令取决于eflags寄存器中的IOPL位。只有IOPL位表示的优先级高于等于当前代码段的优先级时，指令才能执行。<br />    ● I/O操作的保护——I/O地址也是受保护的对象。因为通过I/O操作可以绕过系统对很多硬件进行控制。80386可以单独为I/O空间提供保护，每个任务有个TSS（任务状态段）来记录任务切换的信息。TSS中有个I/O允许位图，用来表示对应的I/O端口是否可以操作。某个I/O地址在位图中的对应数据位为0则表示可以操作；如果为1则还要看eflags中的IOPL位，这时只有IOPL位表示的优先级高于等于当前代码段的优先级，才允许访问该I/O端口。<br />    3. Windows的保护机制<img src ="http://www.cppblog.com/andxie99/aggbug/16687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-12-21 13:07 <a href="http://www.cppblog.com/andxie99/archive/2006/12/21/16687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>8086微处理器的结构</title><link>http://www.cppblog.com/andxie99/archive/2006/12/17/16540.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 17 Dec 2006 04:27:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/12/17/16540.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/16540.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/12/17/16540.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/16540.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/16540.html</trackback:ping><description><![CDATA[<br><br><span class=pt9-black>　　计算机系统包括硬件和软件两部分。微计算机的硬件有包括中央处理器（CPU）的微处理器芯片、存储器（MEMORY）、输入/输出（I/O）接口三部分组成。软件是各种程序的总和，包括系统软件和应用软件。<br><br>　　</span> <span class=part>8086微处理器的基本组成<br></span><span class=pt9-black>
<div align=center><img height=589 alt=2_1.jpg src="http://www.cppblog.com/images/cppblog_com/andxie99/2_1.jpg" width=532 border=0> </div>
<br>
<div align=center>8086微处理器的结构</div>
<br>　<br>　　Intel 8086微处理器是一个16位结构，从图中可以看出，整个微处理器分成两大功能部件，即执行部件（Execution Unit，EU）与总线接口部件（Bus Interface Unit，BIU）。EU与BIU通过内部总线连接，它们既可协同工作，又可独立工作。当EU与BIU各自独立工作时，就体现出8086内部操作具有并行性的特征。<br><br><br>　　<strong>执行部件（EU）</strong><br>　　执行部件EU是执行程序的的核心部件，完成指令译码、运算及其它操作的执行。执行部件由ALU（算术逻辑运算部件）、通用寄存器组、状态标志寄存器以及控制电路组成。<br><br><br>　　<strong>总线接口部件（BIU）</strong><br>　　总线接口部件BIU负责与存储器、I/O接口电路连接，并形成20位的地址码和16位的数据，通过总线进行数据传送。BIU由一些专用寄存器、指令队列缓冲器、地址加法器等功能部件组成。　</span> 
<img src ="http://www.cppblog.com/andxie99/aggbug/16540.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-12-17 12:27 <a href="http://www.cppblog.com/andxie99/archive/2006/12/17/16540.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2006-12-17 周学习计划</title><link>http://www.cppblog.com/andxie99/archive/2006/12/17/16536.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 17 Dec 2006 00:59:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/12/17/16536.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/16536.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/12/17/16536.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/16536.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/16536.html</trackback:ping><description><![CDATA[
		<p>    学习清华大学计算机系网络课程中的汇编语言程序设计。准备花两周来学习，这周主要是理论知识，下周加以实践，写一些Demo。</p>
		<p>12-17：<br />    ★ 第一章 基础知识<br />        ◇第一节　进位计数制<br />        ◇第二节　不同基数的数之间的转换<br />        ◇第三节　二进制数和十六进制数的运算<br />        ◇第四节　数和字符的表示 <br />    ★ 第二章 8086计算机组织 <br />        ◇第一节　80x86微处理器系列概况<br />        ◇第二节　基于8086的微计算机系统<br />        ◇第三节　8086寄存器组<br />        ◇第四节　8086微处理器的存储器管理 <br />        ◇第五节　外部设备 <br />    ★ 第三章 8086的寻址方式和指令系统 <br />        ◇第一节　8086的寻址方式<br />        ◇第二节　机器语言指令的转换<br />        ◇第三节　8086的指令系统<br />12-18：<br />    ★ 第四章 汇编语言程序格式 <br />        ◇第一节　汇编程序功能<br />        ◇第二节　伪指令<br />        ◇第三节　汇编语言程序格式<br />        ◇第四节　汇编语言程序的上机过程 <br />12-19：<br />    ★ 第五章 循环与分支程序设计 <br />        ◇第一节　循环程序设计<br />        ◇第二节　分支程序设计<br />12-20：<br />    ★ 第六章 子程序结构 <br />        ◇第一节　子程序的设计方法<br />        ◇第二节　嵌套与递归子程序<br />        ◇第三节　子程序举例<br />12-21：<br />    ★ 第七章 高级汇编语言技术 <br />        ◇第一节　宏汇编<br />        ◇第二节　重复汇编<br />        ◇第三节　条件汇编<br />        ◇第四节　高级语言结构 <br />12-22：<br />    ★ 第八章 输入／输出程序设计 <br />        ◇第一节　I/O设备的数据传送方式<br />        ◇第二节　程序直接控制I/O方式<br />        ◇第三节　中断传送方式<br />12-23：<br />    ★ 第九章 BIOS和DOS中断 <br />        ◇第一节　键盘I/O<br />        ◇第二节　显示器I/O<br />        ◇第三节　打印机I/O<br />        ◇第四节　串行通信口I/O <br />    ★ 第十章 模块化程序设计 <br />        ◇第一节　汇编程序概述<br />        ◇第二节　连接程序及对程序设计的要求<br />        ◇第三节　汇编语言程序与高级语言程序的连接<br />        ◇第四节　模块化程序设计概述  <br />下周的计划：<br />    ★ 第十一章 80x86汇编语言简介 <br />        ◇第一节　80x86的寄存器结构<br />        ◇第二节　80x86的指令系统和寻址方式<br />        ◇第三节　80x86处理器选择伪操作<br />        ◇第四节　保护模式下的80x86 <br />        ◇第五节　虚拟8086（V86）方式<br />        ◇第六节　保护方式下的中断处理 <br /> <br /></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/16536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-12-17 08:59 <a href="http://www.cppblog.com/andxie99/archive/2006/12/17/16536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#中一种执行命令行或DOS内部命令的方法</title><link>http://www.cppblog.com/andxie99/archive/2006/12/09/16200.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 09 Dec 2006 14:52:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/12/09/16200.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/16200.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/12/09/16200.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/16200.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/16200.html</trackback:ping><description><![CDATA[<font face="Courier New"><br>&nbsp;&nbsp;&nbsp; 用Ping命令作示例，说明C#下执行命令行或DOS内部命令的一种方法，并获取相应的结果。执行时可以让这些程序的执行过程不显示出来，调用外部程序就可以分析执行结果。<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;System;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;要用使用Process类来创建独立的进程,导入</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;System.Diagnostics;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;Cmd<br><img id=Codehighlighter1_82_1799_Open_Image onclick="this.style.display='none'; Codehighlighter1_82_1799_Open_Text.style.display='none'; Codehighlighter1_82_1799_Closed_Image.style.display='inline'; Codehighlighter1_82_1799_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_82_1799_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_82_1799_Closed_Text.style.display='none'; Codehighlighter1_82_1799_Open_Image.style.display='inline'; Codehighlighter1_82_1799_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_82_1799_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_82_1799_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CmdConsole<br><img id=Codehighlighter1_110_1797_Open_Image onclick="this.style.display='none'; Codehighlighter1_110_1797_Open_Text.style.display='none'; Codehighlighter1_110_1797_Closed_Image.style.display='inline'; Codehighlighter1_110_1797_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_110_1797_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_110_1797_Closed_Text.style.display='none'; Codehighlighter1_110_1797_Open_Image.style.display='inline'; Codehighlighter1_110_1797_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_110_1797_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_110_1797_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[STAThread]<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br><img id=Codehighlighter1_181_403_Open_Image onclick="this.style.display='none'; Codehighlighter1_181_403_Open_Text.style.display='none'; Codehighlighter1_181_403_Closed_Image.style.display='inline'; Codehighlighter1_181_403_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_181_403_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_181_403_Closed_Text.style.display='none'; Codehighlighter1_181_403_Open_Image.style.display='inline'; Codehighlighter1_181_403_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_181_403_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_181_403_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.Write(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Please&nbsp;Input&nbsp;IP&nbsp;Address:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;ip&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Console.ReadLine();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;strRst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CmdPing(ip);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(strRst);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.ReadLine();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;CmdPing(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;strIp)<br><img id=Codehighlighter1_474_1791_Open_Image onclick="this.style.display='none'; Codehighlighter1_474_1791_Open_Text.style.display='none'; Codehighlighter1_474_1791_Closed_Image.style.display='inline'; Codehighlighter1_474_1791_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_474_1791_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_474_1791_Closed_Text.style.display='none'; Codehighlighter1_474_1791_Open_Image.style.display='inline'; Codehighlighter1_474_1791_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_474_1791_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_474_1791_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;实例一个Process类,启动一个独立进程</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Process();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;设定程序名</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.FileName&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">cmd.exe</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;关闭Shell的使用</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.UseShellExecute&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;重定向标准输入</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.RedirectStandardInput&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;重定向标准输出</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.RedirectStandardOutput&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">重定向错误输出</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.RedirectStandardError&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;设置不显示窗口</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.CreateNoWindow&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;启动进程</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;pingrst;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.Start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StandardInput.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ping&nbsp;-n&nbsp;1&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;strIp);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StandardInput.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">exit</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;从输出流获取命令执行结果</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;strRst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;p.StandardOutput.ReadToEnd();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(strRst.IndexOf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">(&nbsp;0%&nbsp;loss&nbsp;)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pingrst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">连接</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(strRst.IndexOf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Destination&nbsp;host&nbsp;unreachable.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pingrst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">无法到达目的主机</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(strRst.IndexOf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Request&nbsp;timed&nbsp;out.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pingrst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">超时</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(strRst.IndexOf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Unknown&nbsp;host</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pingrst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">无法解析主机</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pingrst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strRst;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;if&nbsp;end</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.Close();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;pingrst;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
</font>
<img src ="http://www.cppblog.com/andxie99/aggbug/16200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-12-09 22:52 <a href="http://www.cppblog.com/andxie99/archive/2006/12/09/16200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从MFC与ATL的男女关系说起</title><link>http://www.cppblog.com/andxie99/archive/2006/11/16/15196.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Thu, 16 Nov 2006 01:15:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/11/16/15196.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/15196.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/11/16/15196.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/15196.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/15196.html</trackback:ping><description><![CDATA[
		<div class="arcTitle">
				<h3>
						<a href="http://tech.163.com/06/0704/11/2L6CBCLN00091LRC.html#" target="_blank">
						</a> </h3>
		</div>
		<div id="endText">
				<p style="TEXT-INDENT: 2em">
				</p>
				<p style="TEXT-INDENT: 2em">
						<strong>
						</strong>
				</p>如果从哲学的观点来看，这大概要说是一种辩证关系了!<p style="TEXT-INDENT: 2em">首先谈谈男人。男人与男孩的区别在于责任，对于一个男人来说，他的肩膀永远有负担，他要解决生活中遇到的所有问题，可以为妻儿带来幸福生活，可以赡养父母，可以做一些成就来创一番事业。所以男人不要轻生，因为你垮下就意味着你的负担没有了支撑，也就是你不负责任。男人的这种责任体现了一种刚性，打不倒压不垮，坎坎坷坷一路走来即使没有扬名立万但是肩膀上的负担始终没有落下。铮铮铁骨、铁血男儿、阳刚之美都是对男人的赞美，一个家庭男人是顶梁柱，这就是责任。</p><p style="TEXT-INDENT: 2em">再谈谈女人。女人与女孩的区别在于柔情，少了撒娇和任性，多了体贴和温柔。女人是生活的调剂品，少了她尽管可以填抱肚皮、补充营养但食之无味。女人天生就是善于交际的，这本身体现的就是一种柔性，就像太极一样，以柔克刚，借助刚性体现柔美。</p><p style="TEXT-INDENT: 2em">用建筑来形容男女关系，男人就像钢筋水泥搭建起来的框架承受着外力，女人则是对框架填补装修使其美观，不同的男人有着不同的建筑风格，不同的女人可以使建筑呈现不同的美。成功的男人背后都有一个女人，钢筋水泥加上精心装饰让人体会到设计之美，至于谁重要次要，谁表谁里都不是关键，关键的是刚柔的结合。</p><p style="TEXT-INDENT: 2em">MFC</p><p style="TEXT-INDENT: 2em">MFC是一个男人，从Microsoft C/C++ version 7.0到Visual Stduio.net 2005一直承担着软件框架设计的角色，风风雨雨路不回头，屹立在软件设计大道，为开发者提供便利，著名的BCG库和XTREME库都是在MFC源码基础上的改进。它大而繁杂，曲折通幽，粗旷豪放。它必须承担责任，提供软件设计的一套解决方案，而且背负着历史包袱，所以难免带有一些成熟男人的深邃而不被人理解。如果你还一味的去批判它，那只能说你不懂男人的心，不理解一个男人难言之苦。 ATL</p><p style="TEXT-INDENT: 2em">ATL是一个女人，小巧灵活讨人喜爱，它作为COM思想的实现而拿出来解决软件协作的问题。它可以不具体实现功能而只留出一些接口，接口两端相通并且随时拔插，多么完美一个女人!为一个C++对象配备一个ATL对象你可以想象有什么结果嘛?</p><p style="TEXT-INDENT: 2em">软件设计中的MFC与ATL</p><p style="TEXT-INDENT: 2em">以前我一直以为ATL就是做控件、构造插件接口体系的，而MFC就是用来做界面功能。它们属于不同体系，在功能级别上存在差异，所以只是在纵向上结合而没有尝试横向的结合。人类社会是自然的，软件社会也应该是自然的。自然代表一种随和，亲近，协调。</p><p style="TEXT-INDENT: 2em">提到MFC，八九不离十就涉及到软件界面开发。目前来说软件复用需求越来越高，而软件功能的不确定因素越来越大，一个特定的界面行为可能不确定。MFC是一个男人，用它可以做任何想做的界面，这就是它的刚性。但是我们到底是要去做什么还是告诉别人我们可以做什么呢?如果我们一味的做，那我们充其量只是一个莽夫，是吕布有勇无谋。我告诉你我有一个MFC对象，还告诉你它可以做什么，这样不就够了。</p><p style="TEXT-INDENT: 2em">MFC是男人天生缺乏沟通能力，所以无法告知外界它自身的行为，只有它自己知道。这时候就需要一个管子插到对象内部去了解它，而ATL刚好提供了一个接口，将其一段插入MFC对象内部而露出另一端以便告知外界MFC对象内部的行为。这样的界面是可解释的界面，它具有做事情的能力，但是它不去做，而成为可复用界面。</p></div>
<img src ="http://www.cppblog.com/andxie99/aggbug/15196.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-11-16 09:15 <a href="http://www.cppblog.com/andxie99/archive/2006/11/16/15196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>人总要学着跳着长大</title><link>http://www.cppblog.com/andxie99/archive/2006/11/14/15145.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Tue, 14 Nov 2006 03:13:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2006/11/14/15145.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/15145.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2006/11/14/15145.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/15145.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/15145.html</trackback:ping><description><![CDATA[<br>　　　　终于跳槽，感觉一言难尽，总得来说还算好。 
<img src ="http://www.cppblog.com/andxie99/aggbug/15145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2006-11-14 11:13 <a href="http://www.cppblog.com/andxie99/archive/2006/11/14/15145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>