﻿<?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/Zezese/category/13782.html</link><description>记录工作点滴，留下人生轨迹。(zezese@163.com)</description><language>zh-cn</language><lastBuildDate>Thu, 02 Feb 2012 11:21:28 GMT</lastBuildDate><pubDate>Thu, 02 Feb 2012 11:21:28 GMT</pubDate><ttl>60</ttl><item><title>【转载】产品经理的主要职责</title><link>http://www.cppblog.com/Zezese/articles/164765.html</link><dc:creator>张志松</dc:creator><author>张志松</author><pubDate>Wed, 01 Feb 2012 02:24:00 GMT</pubDate><guid>http://www.cppblog.com/Zezese/articles/164765.html</guid><wfw:comment>http://www.cppblog.com/Zezese/comments/164765.html</wfw:comment><comments>http://www.cppblog.com/Zezese/articles/164765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Zezese/comments/commentRss/164765.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Zezese/services/trackbacks/164765.html</trackback:ping><description><![CDATA[<p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">做为一名新进产品经理，甚至一名资深PM，你可能都或多或少对这个职位产生某种迷惑。到底<a href="http://www.chinaz.com/manage/2011/1012/213376.shtml" target="_blank" style="color: #1c3d72; text-decoration: none; ">什么是产品经理</a>？这个职位的主要职责是什么？在IT产业的不同领域，甚至在同一领域的不同公司，这个职位的定义似乎都有不同。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">本文尝试根据自己多年的产品经理经验，给出产品经理的主要职责。 虽然在不同的公司，产品经理的角色和职责互有差异，但是有一些关键职责是任何一个产品经理都应承担的。可以将其归纳为如下六个方面：</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; "><strong>1、市场调研</strong></p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">市场调研是指研究市场以了解客户需求、竞争状况及市场力量（market forces），其最终目标是发现创新或改进产品的潜在机会。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">可以通过下面的方式进行市场调研：</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">与用户和潜在用户交流</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">与直接面对客户的一线同事如销售、客服、技术支持等交流</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">研究市场分析报告及文章</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">试用竞争产品</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">仔细观察用户行为等</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">市场调研最终会形成商业机会、产品战略或商业需求文档（BRD），详述如何利用潜在的机会。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; "><strong>2、产品定义及设计</strong></p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">a） 产品定义是指确定产品需要做哪些事情。通常采用产品需求文档（PRD）来进行描述，PRD可能包含如下信息：</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品的愿景</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">目标市场</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">竞争分析</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品功能的详细描述</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品功能的优先级</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品用例（UseCase）</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">系统需求</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">性能需求</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">销售及支持需求等</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">b） 产品设计是指确定产品的外观，包括用户界面设计（UI，User Interface）和用户交互设计（User Interaction），包含所有的用户体验部分。在大型公司里，PM通常和UI设计师或互动设计师一起完成产品设计，不过在小公司或者创业公司里，产品经理也许需要全包这些工作。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">这是产品经理工作中最有价值的部分， 如果产品经理工作中不包含这部分内容，那几乎可以肯定滴说，那不是产品经理的工作。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; "><strong>3、项目管理</strong></p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">项目管理是指带领来自不同团队的人员（包括工程师、QA、UI设计师、市场、销售、客服等），在预算内按时开发并发布产品。其中可能包括如下工作内容：</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">确保资源投入</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">制定项目计划</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">根据计划跟踪项目进展</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">辨别关键路径</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">必要时争取追加投入</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">向主管领导报告项目进展状况等</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">在大型公司里，通常会有项目经理来处理大部分项目管理工作，产品经理只需提供支持。不过在创业公司里，产品经理通常需要自己进行项目管理。在有些公司，技术负责人也可能做为项目经理，处理大部分项目管理事宜。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; "><strong>4、产品宣介</strong></p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">主要包括和内部同事如老板、销售、市场、客服等沟通产品的优点、功能和目标市场，也可能包括向外界如媒体、行业分析师及用户宣介产品。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">大公司的产品经理通常都有产品市场、市场推广和媒体关系（PR）团队帮忙进行对外的产品宣介。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">这是除了产品定义和设计之外，对产品经理而言价值第二高的工作，尤其是在向老板、市场同事宣介产品并让他们感到兴奋的时候。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; "><strong>5、产品市场</strong></p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">主要是对外的信息传播&#8212;&#8212;告诉外界有关产品的信息。通常包括制作产品数据表、手册、网站、Flash演示、媒体专题以及展会演示等。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">在大型公司，产品市场工作通常不会由PM来负责，这些公司会有专门的产品市场经理来打理此项工作。当然，这种分工最大的缺点就是导致沟通效率较低，并会削弱对外传播。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">在某些公司，&#8220;产品管理&#8221;和&#8220;产品市场&#8221;被认为是同义词，会由一个人担当两者的职责。而在那些将产品管理团队和产品市场团队分开的公司，后者会打理本节所提及的工作职责，同时他们也可能会承担&#8220;市场调研&#8221;、&#8220;产品宣介&#8221;和&#8220;产品生命周期&#8221;管理的部分工作。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; "><strong>6、产品生命周期管理</strong></p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">指那些随着产品经历概念化-&gt;发布-&gt;成熟-&gt;退出市场整个生命周期中的产品管理活动。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">主要包括的工作有：</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品定位</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品定价及促销</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品线管理</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">竞争策略</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">建立或收购合作伙伴</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">识别并建立合作关系等</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">产品经理和产品市场、BD及市场沟通同事一起完成这些工作。</p><p style="margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; font-family: 'Segoe UI', Tahoma, Arial; line-height: 26px; -webkit-text-size-adjust: none; background-color: #f5faff; ">希望这篇文章有助于你了解产品经理（包括产品市场经理），以及他们在公司中密切合作的部门，并祝你成长为一名优秀的产品经理。</p><img src ="http://www.cppblog.com/Zezese/aggbug/164765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Zezese/" target="_blank">张志松</a> 2012-02-01 10:24 <a href="http://www.cppblog.com/Zezese/articles/164765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转 MAP原理及其在MFC中的实现  </title><link>http://www.cppblog.com/Zezese/articles/143014.html</link><dc:creator>张志松</dc:creator><author>张志松</author><pubDate>Wed, 30 Mar 2011 06:01:00 GMT</pubDate><guid>http://www.cppblog.com/Zezese/articles/143014.html</guid><wfw:comment>http://www.cppblog.com/Zezese/comments/143014.html</wfw:comment><comments>http://www.cppblog.com/Zezese/articles/143014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Zezese/comments/commentRss/143014.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Zezese/services/trackbacks/143014.html</trackback:ping><description><![CDATA[MAP原理及其在MFC中的实现
<div id=app-share-container>
<div id=appShareOpt></div>
<div id=app-share-content>
<p><strong>一、 Map的基本知识<br><br></strong>　　映射（Map），又称为字典（Dictionary），是由关键字（Key）及其对应的元素值（Value）所组成的元素单元（Element）的表单式集合。<br><br>　　通常，对于Map而言，使用给定的Key，可以迅速地从单元集合中检索到相应的元素。因此，在需要对大量数据进行查找操作而查找的性能又占据重要地位的场合，Map无疑是一种较理想的容器。譬如，在MFC中，使用Map来实现HandleMaps（句柄映射），以及其他的一些内部数据结构。同时，MFC也提供了公共Map类。使用公共Map类，MFC程序员可以轻易地高效地根据自身的需求实现程序中自定义的映射。<br><br>　　通常，当一个Map对象被删除时，或者，当其中的元素被移除时，关键字和元素值也将被完全删除。<br><br>　　从数据结构的角度分析，有关Map的典型操作有：<br><br>　　1、向Map中插入具有给定关键字的元素单元。<br><br>　　2、在Map中查找具有给定关键字的元素单元。<br><br>　　3、在Map中删除具有给定关键字的元素单元。<br><br>　　4、枚举（遍历）Map中的所有元素单元。<br><br>　　MFC中的各种Map实现，都提供了实现上述操作的成员函数。为了方便讨论，我们以CMap为代表，进行讲解。<br><br>　　一旦你已经向Map中插入了一个关键字-元素值组合对(Key-Value pair)单元，就可以利用关键字访问Map，从而有效地检索、添加或者删除元素单元，也可以遍历Map中的所有单元。<br><br>　　对MFC中的CMap等，除了关键字访问方法之外，还有另一种不同的类型--POSITION，也可以作为访问元素单元的辅助方式，可以使用一个POSITION来"记住"一个元素单元或者对Map进行枚举操作。你可能认为这种使用POSITION实现的遍历等同于使用关键字来进行的Map遍历，事实上并非如此，确切的说，两种检索的等价性是不确定的。<br><br>　　MFC中的提供了基于模板的CMap类。利用CMap模板类，可以处理特定的数据类型，例如用户自定义的类或结构体等。同时，MFC也提供了基于指定数据类型的非模板类，其中包括： <br><br>
<table cellSpacing=0 cellPadding=1 width=500 align=center border=1>
    <tbody>
        <tr>
            <td>类名</td>
            <td>关键字类型</td>
            <td>元素值类型</td>
        </tr>
        <tr>
            <td>CMapWordToPtr</td>
            <td>WORDS</td>
            <td>Void pointers</td>
        </tr>
        <tr>
            <td>CMapPtrToWord</td>
            <td>Void</td>
            <td>pointers WORDS</td>
        </tr>
        <tr>
            <td>CMapPtrToPtr</td>
            <td>Void pointers</td>
            <td>Void pointers</td>
        </tr>
        <tr>
            <td>CMapWordToOb</td>
            <td>WORDS</td>
            <td>Objects</td>
        </tr>
        <tr>
            <td>CMapStringToOb</td>
            <td>Strings</td>
            <td>Objects</td>
        </tr>
        <tr>
            <td>CMapStringToPtr</td>
            <td>Strings</td>
            <td>Void pointers</td>
        </tr>
        <tr>
            <td>CMapStringToString</td>
            <td>Strings</td>
            <td>String</td>
        </tr>
    </tbody>
</table>
二、 <strong>Map的工作原理</strong><br><br>　　使用Map的最大优势是它的快速查找的优秀性能，而取得最优性能的关键在于尽量使得在检索周期内所需进行的元素检查（比对）次数达到最少。顺序查找的性能是最差的，因为如果使用顺序查找算法在包含n个元素单元的Map中查找某个元素，可能（最坏情况下）需要进行n次独立的比较运算。<br><br>　　二元查找（折中查找）的性能表现要稍好一些，可是，一个不容忽视的问题是--二元查找要求待查序列为有序排列，这无疑会降低Map自身的操作灵活性。在我们的理解中，所谓的最佳算法应当是不论元素单元数目的多少，也不论元素是以什么顺序进行排列，查找过程都无需任何额外的比对操作，而能够仅仅通过简单的计算方法，就可以直接指向最终的相应元素的快速、高效算法。这听起来有些玄乎，但事实上，这种算法的确是有可能实现的（而且，我相信，Map可以做得到）。<br><br>　　在MFC的CMap及其相关的Map类中，只要对Map进行正确设置，Lookup函数通常能够一次到位的查找到任意元素，而很少需要进行两次或者三次以上的查找比对。<br><br>　　那么，这种高效的查找是如何实现的呢？<br><br>　　不失一般性，以MFC中的CMap模板类为例。在Map被创建之后（通常是恰恰在第一个元素被插入之前的瞬间），系统会为一个指向CAssoc结构体的指针数组的哈希表分配内存。MFC使用CAssoc结构体描述元素值和关键字的组合对。<br><br>　　CAssoc结构体描述如下：<br><br>
<table width=500 align=center bgColor=#ebe9eb border=0>
    <tbody>
        <tr>
            <td>struct CAssoc<br>　{<br>　　CAssoc* pNext;<br>　　UINT nHashValue;<br>　　CString key;<br>　　CString value;<br>　};</td>
        </tr>
    </tbody>
</table>
<br>　　 无论何时，只要有一个元素值-关键字单元被加入到Map中，就会随之创建一个新的CAssoc结构体，并根据单元中的关键字的实际值来计算出相应的哈希值。同时，拷贝一个指向CAssoc结构体的指针并将其插入到哈希表中索引值为i的位置中。其中，i的计算公式如下：<br><br>　　i=nHashValue%nHushTableSize<br><br>　　式中，nHashValue是由关键字Key的实际值计算出来的哈希值；nHashTableSize是哈希表中元素的数目（默认情况下，哈希表的大小为17）。<br><br>　　如果在哈希表中的索引值为i的位置已经容纳了一个CAssoc指针，那么MFC将建立一个单独的CAssoc结构体的链表（List）,链表中的第一个CAssoc结构体的地址被存储到哈希表中，而将第二个CAssoc结构体的地址存储到前一个CAssoc结构体的pNext域，以此类推。下图展示了哈希表的一种可能实现情况，在该哈希表中，共有10个元素，其中5个元素地址分别唯一的存储，另外5个分别存储在长度为2和3的两个链表中。 <br><br>
<table width=396 align=center border=0>
    <tbody>
        <tr>
            <td><img height=293 src="http://www.yesky.com/SoftChannel/72342371928702976/20010904/jt-2001-8-27-image002.jpg" width=354 align=middle></td>
        </tr>
    </tbody>
</table>
<br>　　调用一个Map的Lookup()函数时，MFC根据输入的关键字的实际值计算相应的哈希值，然后使用前面提到的公式将哈希值转换为索引值，并从哈希表中的相应位置检索CAssoc指针。<br><br>　　理想情况下，该位置只包含一个CAssoc指针，而非CAssoc指针链表。如果事实情况真如同我们所期望的那样，单一地址对应单一CAssoc指针，那么，元素单元将能够被一次查找到位，并直接读出；如果从哈希表中检索到的是CAssoc链表的指针头地址，则MFC顺序比对链表元素CAssoc结构所包含的关键字，直至查找到正确结果。但是，正如我们先前所讨论的那样，只要正确设置Map，链表中的元素一般就不会超过三个，这就意味着，查找通常可以在三次元素比对操作之内完成。<br><strong>三、 优化查找效率<br><br></strong>　　在MFC的Map中，查找性能主要依赖于两个因素：<br><br>　　　1、哈希表的大小<br><br>　　　2、尽可能产生唯一哈希值的优异算法<br><br>　　哈希表的大小对于Map的查找性能而言，是非常重要的。举个简单的例子，如果有一个Map要容纳1000个元素单元，但是哈希表却只能提供17个存放CAssoc指针的空间，那么，即使是最佳情况，哈希表中的每个CAssoc链表中也将包含58或59个CAssoc结构体，自然，在这种情况下，查找性能将受到严重阻碍。<br><br>　　哈希算法亦是影响查找效率的重要因素之一。如果所使用的哈希算法只能产生少量的不同哈希值（从而也只能产生少量的不同的哈希表索引值），查找性能也同样将被降低。<br><br>　　优化Map查找性能的最有效途径是尽可能的增大哈希表以降低因索引值相同而产生冲突的可能。微软推荐将哈希表的大小设置为Map中所存储元素数目的110% ～120%，以使得Map的应用性能在内存消耗和查找效率之间取得相对平衡。<br><br>　　在MFC中，指定哈希表大小，可调用InitHashTable()函数：<br><br>　　　　 map.InitHashTable(1200);<br><br>　　式中，假设Map中要存储1000个元素，按照微软公司的推荐，将哈希表的大小扩展到实际存储元素数目的120%，即设置Map大小为1200。<br><br>　　从统计学上考虑，实用奇数作为哈希表的大小也将有助于减少冲突的发生。因此，初始化一个存储1000个元素的哈希表的InitHashTable()函数可以如下形式使用：<br><br>　　　　　map.InitHashTable(1201);<br><br>　　同时，在InitHashTable()函数的调用时机上，应该注意的是，该函数应当在map包含有任何元素之前使。如果map中已经包含了一个或者更多的元素，那么，重新改变map的大小，将会引发断言（Assertion）错误。<br><br>　　尽管MFC中所使用的哈希算法能够适应于大多数场合，但如果您真的有所需要，或者，只要你愿意，用户也可以使用自己的算法来取代原有的算法。对于一个输入的关键字的值，要计算出它的哈希值，MFC通常调用一个全局模板函数HashKey()，对于大多数数据类型而言，HashKey()函数是以下面的方式实现的：<br><br>
<table width=500 align=center bgColor=#ebe9eb border=0>
    <tbody>
        <tr>
            <td><br>AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)<br>　{<br>　　file://<font color=#cc0000>一般情况的默认算法。</font><br>　　return ((UINT)(void*)(DWORD)key) &gt;&gt; 4;<br>　}<br><br>　　<font color=#ff0000>但对于字符串而言，其具体的实现方式如下：</font><br><br>　UINT AFXAPI HashKey(LPCWSTR key) // <font color=#cc0000>Unicode编码字符串</font><br>　　{<br>　　　UINT nHash = 0;<br>　　　while (*key)<br>　　　　nHash = (nHash&lt;&lt;5) + nHash + *key++;<br>　　　return nHash;<br>　　}<br><br>　UINT AFXAPI HashKey(LPCSTR key) file://<font color=#cc0000> ANSI编码字符串</font><br>　　{<br>　　　UINT nHash = 0;<br>　　　while (*key)<br>　　　　nHash = (nHash&lt;&lt;5) + nHash + *key++;<br>　　　return nHash;<br>　　}</td>
        </tr>
    </tbody>
</table>
　<br>　　要实现对应于特定数据类型的用户自定义哈希算法，您可以使用上述的字符串版本的HashKey()函数作为参考，写一个类似的特定类型的HashKey()函数。</p>
<p><strong>四、 使用MFC中的CMap类<br><br></strong>　　有关MFC中的CMap类的概况，上面的文字段落中已经陆续提及，在此不再赘言。下面，列出CMap类的基本成员函数，并通过一个简短的程序片段来粗略地演示CMap类的使用方法。<br><br>　　构造函数：<br><br>　　<br>
<table cellSpacing=0 cellPadding=1 width=500 align=center border=1>
    <tbody>
        <tr>
            <td>CMap</td>
            <td>构造一个关键字和元素值映射的集合类。</td>
        </tr>
    </tbody>
</table>
<br>　　操作：<br><br>　　　<br>
<table cellSpacing=0 cellPadding=1 width=500 align=center border=1>
    <tbody>
        <tr>
            <td width=99>Lookup</td>
            <td width=391>通过给定的关键字查找相应的元素值。</td>
        </tr>
        <tr>
            <td width=99>SetAt</td>
            <td width=391>向Map中插入一个元素单元；若存在匹配键字，则替代之。</td>
        </tr>
        <tr>
            <td width=99>operator []</td>
            <td width=391>向Map中插入一个元素 -SetAt的子操作</td>
        </tr>
        <tr>
            <td width=99>RemoveKey</td>
            <td width=391>移除由关键字标示的元素单元</td>
        </tr>
        <tr>
            <td width=99>RemoveAll</td>
            <td width=391>移除Map中的所有元素单元</td>
        </tr>
        <tr>
            <td width=99>GetStartPosition</td>
            <td width=391>返回第一个元素单元的位置</td>
        </tr>
        <tr>
            <td width=99>GetNextAssoc</td>
            <td width=391>读取下一个元素单元</td>
        </tr>
        <tr>
            <td width=99>GetHashTableSize</td>
            <td width=391>返回哈希表的大小（元素单元的数目）</td>
        </tr>
        <tr>
            <td width=99>InitHashTable</td>
            <td width=391>初始化哈希表，并指定它的大小</td>
        </tr>
    </tbody>
</table>
<br>　　状态：<br><br>
<table cellSpacing=0 cellPadding=1 width=500 align=center border=1>
    <tbody>
        <tr>
            <td width=130>GetCount</td>
            <td width=360>返回Map中元素的数目</td>
        </tr>
        <tr>
            <td width=130>IsEmpty</td>
            <td width=360>检查Map是否为空（无元素单元）</td>
        </tr>
    </tbody>
</table>
<br>　　应用实例如下：<br>
<table width=500 align=center bgColor=#ebe9eb border=0>
    <tbody>
        <tr>
            <td><br>CMap myMap;<br><br>　file://<font color=#cc0000>初始化哈希表，并指定其大小（取奇数）</font>。MyMap.InitHashTable(257);<br><br>　file://<font color=#cc0000>向myMap中添加元素单元。</font><br>for (int i=0;i &lt; 200;i++)<br>　myMap.SetAt( i, CPoint(i, i) );<br><br>　file://<font color=#cc0000> 删除实际值为偶数的关键字所对应的的元素单元。</font><br>　POSITION pos = myMap.GetStartPosition();<br>　int nKey;<br>　CPoint pt;<br>　while (pos != NULL)<br>　{<br>　　myMap.GetNextAssoc( pos, nKey, pt );<br><br>　　if ((nKey%2) == 0)<br>　　　myMap.RemoveKey( nKey );<br>　}<br><br>　#ifdef _DEBUG<br>　　afxDump.SetDepth( 1 );<br>　　afxDump &lt;&lt; "myMap: " &lt;&lt; &amp;myMap &lt;&lt; "\n";<br>　#endif</td>
        </tr>
    </tbody>
</table>
<br>　　在上面的应用程序片段中，我们可以了解有关CMap类的在通常情况下的使用方法。<br><br>　　　1、首先我们使用CMap模板类来定义一个实例--myMap对象。<br><br>　　　2、紧接着要做的是对myMap对象的哈希表的大小进行初始化设置。此时，应该先对myMap可能的容量需求进行估计，然后选择适当大小的奇数--或者，有可能的话，使用素数的效果会更好一些--来作为哈希表的初始值。<br><br>　　　3、然后，向myMap中添加元素单元。<br><br>　　　4、使用myMap进行数据映射、查找、遍历等操作。<br><br>　　　5、调用myMap.RemoveAll()函数移除所有元素，释放myMap占用的内存空间。<br><br>　　CMap对应IMPLEMENT_SERIAL，从而支持用户对其元素进行串行化（Serialization）以及倾注（Dumping）操作。在对CMap的独立元素进行倾注操作时，应该注意的是，你必须将倾注环境（Dump Context）的深度设置为1或者更大的数字。<br><br>　　经过上述讨论，相信大家对Map及其在MFC中的实现都有了一定的了解，希望此文章能够给大家带来一点帮助。也希望朋友们多联系、多指教，我的E-mail：purestain@sina.com。谢谢！</p>
</div>
</div>
<img src ="http://www.cppblog.com/Zezese/aggbug/143014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Zezese/" target="_blank">张志松</a> 2011-03-30 14:01 <a href="http://www.cppblog.com/Zezese/articles/143014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己编译 MFC 库</title><link>http://www.cppblog.com/Zezese/articles/115120.html</link><dc:creator>张志松</dc:creator><author>张志松</author><pubDate>Tue, 11 May 2010 09:07:00 GMT</pubDate><guid>http://www.cppblog.com/Zezese/articles/115120.html</guid><wfw:comment>http://www.cppblog.com/Zezese/comments/115120.html</wfw:comment><comments>http://www.cppblog.com/Zezese/articles/115120.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Zezese/comments/commentRss/115120.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Zezese/services/trackbacks/115120.html</trackback:ping><description><![CDATA[<p>自己编译 MFC 库（转载）<br><br></p>
<p>作者：朱之光<br></p>
<p><br>MFC也是人做的，难免有错。vs2003三年都没有patch了。<br>如果不幸碰上了MFC中的bug，那么就动手修改他再进行编译吧。</p>
<p>1、设置编译环境<br>其实很简单就是执行Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat<br>接下来开启一个cmd.exe<br>进入目录Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc</p>
<p><br>2、编译<br>首先确定要编译什么样的MFC库<br>makefile用于编译静态MFC库；mfcdll.mak用于编译MFC动态连接库</p>
<p>1）静态连接库<br>nmake DEBUG=1 BROWSE=1 CODEVIEW=1</p>
<p>按下回车就可以了<br>编译完成后<br>在Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\lib\INTEL目录下<br>能够找到刚刚编译完成的UafxcWD.lib</p>
<p>把它复制到Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\lib<br>（记得备份老的库）</p>
<p>2）动态连接库<br>nmake /f mfcdll.mak DEBUG=1 BROWSE=1 CODEVIEW=1 PLATFORM=INTEL LIBNAME=myMFC71</p>
<p>按下回车就可以了<br>编译完成后<br>在Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc\intel目录下<br>能够找到刚刚编译完成的myMFC71UD.dll</p>
<p>在Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\lib\INTEL目录下<br>能够找到刚刚编译完成的myMFC71UD.LIB</p>
<p>注意动态连接库一定不要使用mfc71这个LIBNAME，否则别人系统上的MFC71库并没有经过你修改，而你的程序又连接了mfc71ud.dll，这样会导致程序出错。</p>
<p>以后编译程序的时候，就可以使用自己编译出来的库了</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/Zezese/aggbug/115120.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Zezese/" target="_blank">张志松</a> 2010-05-11 17:07 <a href="http://www.cppblog.com/Zezese/articles/115120.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>