冷夜 C++ 小栈

关于C++的一些经验与心得,还会有一些技术文摘

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  6 Posts :: 5 Stories :: 12 Comments :: 0 Trackbacks

常用链接

留言簿(10)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

2007年7月13日 #


----------------------------------------
上位机一般是集中管理监控机,下位机是指现场直接控制器或控制机。  
  上位机面向管理级用户,下位机面向底层设备控制。

--------------------------------------
上位机:上位监视系统,一般为计算机系统(监控软件);
下位机:控制系统的现场执行系统,一般为PLC等设备。

--------------------------------------
上位机是指人可以直接发出操控命令的计算机,一般是PC,屏幕上显示各种信号变化(液压,水位,温度等)。
下位机是直接控制设备获取设备状况的的计算机,一般是PLC/单片机之类的。上位机发出的命令首先给下位机,下位机再根据此命令解释成相应时序信号直接控制相应设备。下位机不时读取设备状态数据(一般模拟量),转化成数字信号反馈给上位机。简言之如此,真实情况千差万别不离其宗。上下位机都需要编程,都有专门的开发系统。

两机如何通讯,一般取决于下位机。TCP/IP一般是支持的。但是下位机一般具有更可靠的独有通讯协议,购买下位机时,会带一大堆手册光盘,告诉你如何使用特有协议通讯。里面会举大量例子。一般对编程人员而言一看也就那么回事,使用一些新的API罢了。多语言支持功能模块,一般同时支持数种高级语言为上位机编程。

---------------------------------------
上位机是指工业控制中位于较高层次的计算机。上位机通常指电脑了
下位机就通常指单片机之类

---------------------------------------
下位机一般指放置在前端的采集机,比如AD4500等设备,用来采集智能设备数据,并把数据通过串口或者其它方式发送给服务端。下位机一般具有自检和自启功能,是一种小型的计算机,功能比较单一,使用DOS操作系统或其它操作系统。上位机是相对于下位机而言,一般情况下一个上位机对应几个下位机,把下位机的数据转发给服务器或者把服务器的控制信息发送给下位机。有时候上位机本身就充当服务器。


posted @ 2007-07-13 14:52 冷夜 阅读(1614) | 评论 (0)编辑 收藏

2005年9月13日 #

      软件工艺(software craftsmanship),今天第一次看到这个名词好像有点后知后觉。但是我确实觉得"软件工艺"一词要比软件工程能够更好地揭示软件设计与开发的过程与技术特点。
      看到软件工艺这个名词是在一个网友的blog,软件工艺是国外一本书的名字,据说中译版即将在国内发行。找时间应该了解一下此书的主要观点,或许对于软件设计与开发的思想会有所帮助。
posted @ 2005-09-13 21:45 冷夜 阅读(526) | 评论 (2)编辑 收藏

 

X君最初的工作任务是设计制作公司的官方网站。对于“能熟练使用Photoshop、Dreamweaver等软件”的X君,这不是一件复杂的工作。但是,要求他在一周之内交上来的网站建设策划,直等了一个月,我才收到一张A4纸。上面用四号字写了大概20行。

六级英语水平,编辑一些国外的资讯应该没有问题吧?……X君遇到了大麻烦。因为对杂志所专向的电脑技术、电脑游戏不熟悉,很多“专业术语”在X君的眼里,简直就是“天书”!……X君在编辑部坐了一个月,没有编译出一篇稿件,只好帮着做了一点文字校对。

自然有网友给X君打抱不平。譬如从回复中摘出的两段:

MCSE是什么?它代表的是Windows系统管理的水平。因此,这家公司要求他去做网站,他的表现不好,公司的人由此认定“MCSE就这个水平”未免太荒唐。

想看看这个学生英语水平如何,找个英语好的人跟他对对话,让他写几个两、三千字的材料就可以看出来了。那是基本功,假不了的。至于专业术语的问题,在业内摸爬滚打个把月也就逐渐熟悉了。

我想说的是,第一,企业要的是创造价值的人才,不能创造价值,纵有千般武功,也是废人一个。不过这不是关键,关键在于,必须看到,这位X君太不喜欢——这是我跟新员工常提的一个字。不会做事没关系,你有时间学,但你首先必须学会喊:要做任何事,先喊出来,让所有相关的人都知道你要做什么,打算怎么做;做完一件事,要喊出来,让大家看到你的成绩;遇到问题了,更要毫不犹豫地喊出来,让别人知道状况,甚至给你帮助。在我看来,能力是人和人不同的,学习也有机遇等等各方面的区别,但无论如何,只要喊出来,至少不会像X君这样“速败”而一败涂地。

从我个人的经验而言,凡是败得很难看的事情,大抵都是自己懒得喊造成的。所以,这篇也写给自己留底:以后做事还要多喊。对于类似X君等等刚出或未出校园的同学,我的建议是:尽快忘记“考试不能作弊”的规章制度,做任何事情多说话,邮件也好MSN也好口头也好,说比不说要好,多说比少说要好。另外,昨天晚上和孟岩提到了关于简历的话题,私以为对于初次找工作的同学也是颇有帮助的,看看孟岩要不要在《程序员》杂志上放一放吧。



本文引用通告地址: http://blog.csdn.net/gigix/services/trackbacks/474983.aspx
posted @ 2005-09-13 21:28 冷夜 阅读(443) | 评论 (1)编辑 收藏

 
许多内向型的人希望能够改变自己的内向性格,提高自己与他人交往的能力,进而拥有良好的人际关系。于是他们看了许多人际关系方面的书籍,也学了许多人际关系的技巧,可是却发现收效甚微,效果不明显。这说明光学习技巧是远远不够的。他们无法拥有良好的人际关系不光是因为缺乏技巧,还有许多深层次的原因。同时,这也从一个侧面说明了,现在的人际关系方面的书籍是有缺陷的,是不完整的。内向的人要想拥有良好的人际关系,需要从信念、态度、技巧等多方面改变和提高。


一、信念:树立“双赢”(平等互利)的信念

  要想拥有良好的人际关系,就要有平等、互利的思想。用时髦的话说,就是要有双赢思维。

  在对待人际关系上,存在着以下几种思维模式:

1.我赢你输:
  我们从小受的教育就在加强这种思想观念。考试的时候你要考得比别人好,体育比赛时你要跑得比别人快、跳得比别人高,你要得冠军。总之只有超过别人,只有赢,才能使我们感到快乐。我们把生活看成是竞技场,要成功幸福就要超越别人,把别人甩在后面。
  另外,自私自利的人抱持的也是这种我赢你输的思想。

2.我输你赢:
  缺乏自信、缺乏自尊的人往往是这种思想。
  他们不敢坚持自己的立场,无所欲无所求,牺牲个人利益委曲求全,以牺牲求太平。

3.两败俱伤:
  表面上看这样做谁都得不到好处,似乎没有人会这样做。可是有的人偏偏要这样想、这样做!损人不利己,我得不到的你也别想得到,为了报复,宁可牺牲自己,也要把你拖垮。

4.双赢:
  双赢是建立在平等互利思想的基础之上的。自己获利但又不伤害别人利益。不把自己和别人对立起来,我和你不是敌对的双方,而是同一条战壕里的战友,有富同享,有难同当,共同开创美好的未来。

  我赢你输(自私自利)、我输你赢(委曲求全)、双输(两败俱伤)这些思维模式,都是无法使人拥有良好的人际关系的。要想拥有良好的人际关系,就要有双赢思维,拥有平等、互利的思想。


本文引用通告地址: http://blog.csdn.net/i_like_cpp/services/trackbacks/475017.aspx
posted @ 2005-09-13 21:22 冷夜 阅读(696) | 评论 (1)编辑 收藏

2005年9月12日 #

静态构造函数
静态构造函数是一种成员,用来实现初始化一个类所需的操作。静态构造函数不能带参数,
不能具有可访问性修饰符,也不能被显式调用。类的静态构造函数是自动地被调用的。
(上面的说明摘自《C# Language Specification》)

示例
class Employee
{
 private static int ds;
 static Employee() {
  ds = 2;
 }

 public Employee(int n)
{
    ds = n;
}

 public string Name;
 public decimal Salary;
}
显示了一个 Employee 类,该类含有一个静态构造函数,它初始化一个静态字段

请注意下面的语句,会导致静态构造函数先被调用,然后调用public的构造函数。也就是说执行了
两个不同的构造函数,因此在实际应用中,需要注意到这种情况可能会引起的问题。

Employee em = new Employee(1);


(本文是本人以baodi_z的网名原发表在CSDN的个人BLOG,原文发表于 2005年06月07日 5:44 PM )

posted @ 2005-09-12 23:38 冷夜 阅读(629) | 评论 (0)编辑 收藏

一个有趣的现象,摘自CSDN 吹云Blog《C++从零开始(十二)——何谓面向对象编程思想》原文http://blog.csdn.net/chuiyun/archive/2004/11/26/194722.aspx

    之所以摘录这段文章,是因为我奇怪下面的例子竟然真的能够编译通过--在引用的文件中篡改类的private为public就可以直接访问私有变量,而且能够正常访问和赋值。
    下面是摘录的原文,有兴趣的朋友不妨也试试编个代码试验一下。

-------------------------------------------------------------------

封装

    先来看现在在各类VC教程中关于对象的讲解中经常能看见的如下的一个类的设计。
    class Person
    { private: char m_Name[20]; unsigned long m_Age; bool m_Sex;
      public:  const char* GetName() const;  void SetName( const char* );
               unsigned long GetAge() const; void SetAge( unsigned long );
               bool GetSex() const;          void SetSex( bool );
    };
    上面将成员变量全部定义为private,然后又提供三对Get/Set函数来存取上面的三个成员变量(因为它们是private,外界不能直接存取),这三对函数都是public的,为什么要这样?那些教材将此称作封装,是对类Person的内部内存布局的封装,这样外界就不知道其在内存上是如何布局的并进而可以保证内存的有效性(只由类自身操作其实例)。
    首先要确认上面设计的荒谬性,它是正宗的“有门没锁”毫无意义。接着再看所谓的对内存布局的封装。回想在《C++从零开始(十)》中说的为什么每个要使用类的源文件的开头要包含相应的头文件。假设上面是在Person.h中的声明,然后在b.cpp中要使用类Person,本来要#include "Person.h",现在替换成下面:
    class Person
    { public: char m_Name[20]; unsigned long m_Age; bool m_Sex;
      public: const char* GetName() const;  void SetName( const char* );
              unsigned long GetAge() const; void SetAge( unsigned long );
              bool GetSex() const;          void SetSex( bool );
    };
    然后在b.cpp中照常使用类Person,如下:
    Person a, b; a.m_Age = 20; b.GetSex();
    这里就直接使用了Person::m_Age了,就算不做这样蹩脚的动作,依旧#include "Person.h",如下:
    struct PERSON { char m_Name[20]; unsigned long m_Age; bool m_Sex; };
    Person a, b; PERSON *pP = ( PERSON* )&a; pP->m_Age = 40;
    上面依旧直接修改了Person的实例a的成员Person::m_Age,如何能隐藏内存布局?!请回想声明的作用,类的内存布局是编译器生成对象时必须的,根本不能对任何使用对象的代码隐藏有关对象实现的任何东西,否则编译器无法编译相应的代码。
    那么从语义上来看。Person映射的不是真实世界中的人的概念,应该是存放某个数据库中的某个记录人员信息的表中的记录的缓冲区,那么缓冲区应该具备那三对Get/Set所代表的功能吗?缓冲区是缓冲数据用的,缓冲后被其它操作使用,就好像箱子,只是放东西用。故上面的三对Get/Set没有存在的必要,而三个成员变量则不能是private。当然,如果Person映射的并不是缓冲区,而在其它的世界中具备像上面那样表现的语义,则像上面那样定义就没有问题,但如果是因为对内存布局的封装而那样定义类则是大错特错的。
    上面错误的根本在于没有理解何谓封装。为了说明封装,先看下MFC(Microsoft Foundation Class Library——微软功能类库,一个定义了许多类的库文件,其中的绝大部分类是封装设计。关于库文件在说明SDK时阐述)中的类CFile的定义。从名字就可看出它映射的是操作系统中文件的概念,但它却有这样的成员函数——CFile::Open、CFile::Close、CFile::Read、CFile::Write,有什么问题?这四个成员函数映射的都是对文件的操作而不是文件所具备的功能,分别为打开文件、关闭文件、从文件读数据、向文件写数据。这不是和前面说的成员函数的语义相背吗?上面四个操作有个共性,都是施加于文件这个资源上的操作,可以将它们叫做“被功能”,如文件具有“被打开”的功能,具有“被读取”的功能,但应注意它们实际并不是文件的功能。
    按照原来的说法,应该将文件映射为一个结构,如FILE,然后上面的四个操作应映射成四个函数,再利用名字空间的功能,如下:
    namespace OFILE
    {
        bool Open( FILE&, … );  bool Close( FILE&, … );
        bool Read( FILE&, … );  bool Write( FILE&, … );
    }
    上面的名字空间OFILE表示里面的四个函数都是对文件的操作,但四个函数都带有一个FILE&的参数。回想非静态成员函数都有个隐藏的参数this,因此,一个了不起的想法诞生了。
    将所有对某种资源的操作的集合看成是一种资源,把它映射成一个类,则这个类的对象就是对某个对象的操作,此法被称作封装,而那个类被称作包装类或封装类。很明显,包装类映射的是“对某种资源的操作”,是一抽象概念,即包装类的对象都是无状态对象(指逻辑上应该是无状态对象,但如果多个操作间有联系,则还是可能有状态的,但此时它的语义也相应地有些变化。如多一个CFile::Flush成员函数,用于刷新缓冲区内容,则此时就至少有一个状态——缓冲区,还可有一个状态记录是否已经调用过CFile::Write,没有则不用刷新)。
    现在应能了解封装的含义了。将对某种资源的操作封装成一个类,此包装类映射的不是世界中定义的某一“名词性概念”,而是世界的“动词性概念”或算法中“对某一概念的操作”这个人为定出来的抽象概念。由于包装类是对某种资源的操作的封装,则包装类对象一定有个属性指明被操作的对象,对于MFC中的CFile,就是CFile::m_hFile成员变量(类型为HANDLE),其在包装类对象的主要运作过程(前面的CFile::Read和CFile::Write)中被读。
    有什么好处?封装提供了一种手段以将世界中的部分“动词性概念”转换成对象,使得程序的架构更加简单(多条“动词性概念”变成一个“名词性概念”,减少了“动词性概念”的数量),更趋于面向对象的编程思想。
    但应区别开包装类对象和被包装的对象。包装类对象只是个外壳,而被包装的对象一定是个具有状态的对象,因为操作就是改变资源的状态。对于CFile,CFile的实例是包装类对象,其保持着一个对被包装对象——文件内核对象(Windows操作系统中定义的一种资源,用HANDLE的实例表征)——的引用,放在CFile::m_hFile中。因此,包装类对象是独立于被包装对象的。即CFile a;,此时a.m_hFile的值为0或-1,表示其引用的对象是无效的,因此如果a.Read( … );将失败,因为操作施加的资源是无效的。对此,就应先调用a.Open( … );以将a和一特定的文件内核对象绑定起来,而调用a.Close( … );将解除绑定。注意CFile::Close调用后只是解除了绑定,并不代表a已经被销毁了,因为a映射的并不是文件内核对象,而是对文件内核对象操作的包装类对象。
    如果仔细想想,就会发现,老虎能够吃兔子,兔子能够被吃,那这里应该是老虎有个功能是“吃兔子”还是多个兔子的包装类来封装“吃兔子”的操作?这其实不存在任何问题,“老虎吃兔子”和“兔子被吃”完全是两个不同的操作,前者涉及两种资源,后者只涉及一种资源,因此可以同时实现两者,具体应视各自在相应世界中的语义。如果对于真实世界,则可以简略地说老虎有个“吃”的功能,可以吃“肉”,而动物从“肉”和“自主能动性”多重继承,兔子再从动物继承。这里有个类叫“自主能动性”,指动物具有意识,能够自己动作,这在C++中的表现就是有成员函数的类,表示有功能可以被操作,但收音机也具有调台等功能,难道说收音机也能自己动?!这就是世界的意义——运转。

(本文是本人以baodi_z的网名原发表在CSDN的个人BLOG,原文发表于 2004年12月09日 2:09 PM )

posted @ 2005-09-12 23:35 冷夜 阅读(2136) | 评论 (8)编辑 收藏