Pencil.C++

更新速度可能会晚于http://blog.csdn.net/bilaopao

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  34 随笔 :: 0 文章 :: 40 评论 :: 0 Trackbacks

#

     摘要:   阅读全文
posted @ 2009-06-09 00:06 Pencil.C++ 阅读(591) | 评论 (0)编辑 收藏

一、外挂的分类

外挂一般的分为2类,脱机式 和 内挂式。

脱机式外挂的定义:完全脱离官方发布的客户端程序,可以与游戏服务器自由的进行通讯的外挂程序,这类外挂的实现是2类外挂里最困难的,主要难点在于外挂制作者需要对游戏的通讯协议进行充分的分析,包括解决封包的加密解密问题,使得封包合法化,这样游戏服务器才能接受并处理。

内挂式外挂的定义:内挂需要以官方发布的客户端程序为载体,依靠客户端程序来完成与游戏服务器的通讯,主要通过反汇编手段分析并修改客户端代码后实现功能,一般通过直接调用游戏客户端的发包函数进行发包,或者调用游戏客户端的封包加密解密函数自行处理发包收包。


二、制作外挂常用的技术手段

   制作外挂一般使用的分析工具:
动态分析 OllyDbg(OllyICE)
静态分析 IDA Pro

   制作外挂一般使用的开发工具:
VisualStdio系列(VC++,VB)
Borland系列(Delphi,BCB,BC++)
中国人自己的开发工具(易语言)(编者注:此开发工具优势在于控件种类上,有专门的用于外挂制作的控件)

   制作外挂的技术要点:
鼠标键盘模拟技术:这类技术在RING3层可通过调用WIN32 API实现,在RING0层可通过驱动模拟鼠标键盘输入来实现。按键精灵就采用在RING0层通过驱动来模拟鼠标键盘,比较底层。

Hook技术:包括API HOOK 、普通的对游戏代码进行HOOK等。这类技术有个特点,对目标进程的代码会进行修改。

脚本技术:扩充外挂功能的技术之一,能让外挂使用者编写脚本来扩充外挂功能。

三、反外挂中常用的技术手段

反外挂一般使用的分析工具:
动态分析 OllyDbg(OllyICE)
静态分析 IDA Pro

制作反外挂一般使用的开发工具:
依据游戏客户端采用的开发工具来决定。

制作反外挂的技术要点:
代码校验:包括磁盘代码及内存代码校验,防止代码被非法更改。

虚拟机保护:虚拟机(VM )其实就是Virtual Machine的缩写,这里说的VM并不是像VMWare那样的虚拟机,而是将一系列的指令解释成bytecode(字节码)放在一个解释引擎中执行,能有效的干扰非法调试者对保护的代码进行分析。是反外挂技术中的重中之重。

驱动保护:采用底层钩子技术,一般采用SSDT HOOK来对游戏进程进行保护。但这种技术有一个致命的缺陷,就是兼容性问题。

反调试:对调试过程产生干扰,阻止非法调试者进行正常的调试。反调试代码加多后会导致兼容性稳定性出现问题。

四、一般保护的思路及步骤

   防止脱机式外挂:
合理的设计封包通讯协议及对封包加密解密算法进行虚拟机保护能有效的防止脱机外挂,反脱机外挂的难度比较低。而且技术要求也不高。

   防止内挂式外挂:
反该类外挂主要从代码校验上着手,并配合虚拟机保护,必要时候加上简单的驱动。简单的可以采用如下步骤处理:
(1)        将封包加密解密独立成一个动态连接库(DLL),供游戏主程序调用进行封包加解密。
(2)        更换封包加密解密方式,防止破解者采用替换旧客户端的方式进入游戏。
(3)        反外挂功能在独立出来的动态连接库里实现,在独立出来的动态连接库中加入对主程序代码段校验。建立一个新的反外挂线程来校验代码段,加入敌意进程或模块的特征检测,对关键的API进行检测。检测到非法可以对服务器进行报告,并在客户端主动切断与游戏服务器的连接。
(4)        在加密解密函数里加入对反外挂线程的检测,检测反外挂线程是否正常运行,如果检测到非法情况,同样对服务器进行报告并主动切断与游戏服务器的连接。
(5)        对独立出来的DLL进行虚拟机保护(封包加解密及反外挂线程代码)。
(6)        加入一些反调试技术。
(7)        根据实际情况采用驱动技术,对游戏进行保护。

五、对反外挂工作的建议
反外挂工作具有长期性,复杂性等特性,故建立专门进行此类工作的软件安全小组是必须的,及时的收集外挂后分析外挂的所使用的技术和破解反外挂系统的方式,写出相应的检测及防护代码,提交后进行游戏更新。通过不断的完善反外挂系统,我有理由坚信,外挂会在这样的保护措施下销声匿迹。
posted @ 2009-06-08 23:29 Pencil.C++ 阅读(804) | 评论 (0)编辑 收藏

■1.FindWindow:这个函数返回游戏窗口的句柄。参数lpClassName为游戏的类名(像neoragex这个模拟器的类名为"neoragex",winamp的类名为"Winamp v1.x"),程序的类名可以用game master 获得或自己编程获得,如果实在得不到的话就设为vbNullstring ;参数lpWindowName 为游戏窗口的标题,如果lpClassName设为vbNullstring的话,这个一定要完整,不然将得不到正确的句柄。
■2.GetWindowThreadProcessId:获得游戏的进程标识符。参数hwnd 是findwindow 返回的游戏窗口的句柄;参数lpdwProcessId 就是函数获得的进程标识符,等一下openprocess 要用到的。
■3.openprocess:用来得到游戏进程句柄,参数dwDesiredAccess 的值决定了句柄对进程的存取权利,要设为PROCESS_ALL_ACCESS(完全存取权限);如句柄能够由子进程继承,则把参数bInheritHandle 设为True,而我们要设为False ;dwProcessId 为所要打开游戏的进程标识符,就是用GetWindowThreadProcessId 获得的那个。
■4.WriteProcessMemory :这个函数可是重中之重呀,它用来写游戏内存中指定地址的值。参数hProcess 是想要写的游戏的进程句柄,就是由上面的openprocess函数得到(你想写neoragex 这个模拟器的内存数据,就必须得到neoragex 的进程句柄,就像你想去银行保险箱取钱,你必须知道究竟哪个保险箱是你的一样); 参数lpBaseAddress 是你想修改的游戏的内存地址,像KOF99中1P 人物生命值的地址的十六进制是567BC0,在VB 中,在数字的前面加&H 表示十六进制,在上面的程序中就是&H567BC0 ;参数lpBuffer 是地址的值;参数nSize 是希望写入lpBaseAddress 的字节数,如果你写入的值是Byte,则应为1 ,如果是I n t e g e r ,则应为2 ,以此类推;参数lpNumberOfBytesWritten 不用管它,一般设为0& 即可。
■5 . R e a d P r o c e s s M e m o r y :这个跟上面的WriteProcessMemory 用法差不多,它是用来读取指定游戏内存中指定地址的值的。
■6.CloseHandle :用来关闭每一个打开的进程句柄。剩下的那些就算是菜鸟都能看得懂,我就不废话了。有了这六个强大的API函数,你还怕铸不出绝世的好“剑”?上面这个源程序只是一个简单的例子,凭大家的聪明才智,肯定能做出更加强大的修改器。
posted @ 2009-06-06 16:29 Pencil.C++ 阅读(246) | 评论 (0)编辑 收藏

程序源码如下.

/////////////////////////////////////////////////////////////////////
#include   "windows.h "
#include   "WinIo.h "
#include   "winuser.h "
#include   "iostream.h "
#define   VK_A   0x41

#define   KBC_KEY_CMD   0x64         //键盘命令端口
#define   KBC_KEY_DATA   0x60       //键盘数据端口


void   KBCWait4IBE()
{
DWORD   dwRegVal=0;
do
{  
GetPortVal(0x64,&dwRegVal,1);
}
while(dwRegVal   &   0x00000001);
}

void   MyKeyDownEx(long   vKeyCoad)       //模拟扩展键按下,参数vKeyCoad是扩展键的虚拟码
{
long   btScancode;
btScancode   =   MapVirtualKey(vKeyCoad,   0);

        KBCWait4IBE();       //等待键盘缓冲区为空
        SetPortVal(KBC_KEY_CMD,   0xD2,   1     );       //发送键盘写入命令
        KBCWait4IBE();
        SetPortVal(KBC_KEY_DATA,   0xE0,   1   );   //写入扩展键标志信息
       
       
        KBCWait4IBE();       //等待键盘缓冲区为空
        SetPortVal(   KBC_KEY_CMD,   0xD2,   1   );         //发送键盘写入命令
        KBCWait4IBE();
        SetPortVal(   KBC_KEY_DATA,   btScancode,   1   );   //写入按键信息,按下键
}


void   MyKeyUpEx(long   vKeyCoad)       //模拟扩展键弹起
{
long   btScancode;
btScancode   =   MapVirtualKey(vKeyCoad,   0);

        KBCWait4IBE();       //等待键盘缓冲区为空
        SetPortVal(KBC_KEY_CMD,   0xD2,   1   );         //发送键盘写入命令
        KBCWait4IBE();
        SetPortVal   (KBC_KEY_DATA,   0xE0,   1   );   //写入扩展键标志信息
       
       
        KBCWait4IBE();     //等待键盘缓冲区为空
        SetPortVal(KBC_KEY_CMD,   0xD2,   1   );         //发送键盘写入命令
        KBCWait4IBE();
        SetPortVal(KBC_KEY_DATA,   (btScancode   |   0x80),   1);     //写入按键信息,释放键
}

void   MyKeyDown(long   vKeyCoad)
{
long   byScancode   =   MapVirtualKey(vKeyCoad,0);  
KBCWait4IBE();//等待键盘缓冲区为空  
if(SetPortVal(0x64,0xD2,1)==false)cout < < "发送键盘写入命令失败! " < <endl;//发送键盘写入命令

KBCWait4IBE();//等待键盘缓冲区为空  
if(SetPortVal(0x60,(ULONG)byScancode,1)==false)cout < < "按下键失败! " < <endl;//写入按键信息,按下键
}


void   MyKeyUp(long   vKeyCoad)
{
long   byScancode   =   MapVirtualKey(vKeyCoad,0);  
KBCWait4IBE();//等待键盘缓冲区为空  
if(SetPortVal(0x64,0xD2,1)==false)cout < < "发送键盘写入命令失败! " < <endl;//发送键盘写入命令

KBCWait4IBE();//等待键盘缓冲区为空  
if(SetPortVal(0x60,(ULONG)(byScancode   |   0x80),1)==false)cout < < "释放键失败! " < <endl;//写入按键信息,释放键
}


void   main()
{
if(InitializeWinIo()==false)cout < < "驱动程序加载失败! " < <endl;

Sleep(3000);

MyKeyDownEx(VK_LEFT);       //按下左方向键
Sleep(200);                         //延时200毫秒
MyKeyUpEx(VK_LEFT);           //释放左方向键  
Sleep(500);
MyKeyDown(VK_SPACE);       //按下空格键,注意要发送两次
MyKeyDown(VK_SPACE);
Sleep(200);
MyKeyUp(VK_SPACE   )   ;       //释放空格键

ShutdownWinIo();
}
posted @ 2009-06-06 01:46 Pencil.C++ 阅读(4041) | 评论 (6)编辑 收藏

1.命名管道
2.匿名管道
3.邮槽
4.剪贴板
5.WM_COPYDATA
6.WM_SETTEXT
7.数据共享
8.Socket

说说最简单的WM_COPYDATA
你可以向一个窗口发送WM_COPYDATA消息,用SendMessage
比如你向一个窗口通宵,想发送一个字符串"CIW_BLUE"给另外一个窗口,可以这样:
COPYDATASTRUCT stCopyData = {0};
stCopyData.lpData = "CIW_BLUE";
stCopyData.cbData = strlen("CIW_BLUE")+ 1;
SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&stCopyData);

你在接受的程序里面响应WM_COPYDATA消息就OK
lParam 是一个COPYDATASTRUCT的指针
posted @ 2009-06-02 20:42 Pencil.C++ 阅读(305) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-04-26 15:15 Pencil.C++ 阅读(539) | 评论 (2)编辑 收藏

20. 格式化输入和输出:        例题从 167开始
     A.设置流的格式化标志
        1).控制格式的标志位
         ------------------------------------------------------------------------------
           标志位 |   值                             含义               |输入/输出
         ------------------------------------------------------------------------------
          skipws  | 0x0001 |                 跳过输入中的空白符                   i
         ------------------------------------------------------------------------------
           left   | 0x0002 |                 输出数据左对齐                       o
         ------------------------------------------------------------------------------
          rignt   | 0x0004 |                 输出数据右对齐                       o
         ------------------------------------------------------------------------------
         internal | 0x0008 |   数据的符号左对齐,数据本身右对齐,之间为填充符     o
         ------------------------------------------------------------------------------
           dec    | 0x0010 |              转换基数为十进制形式                   i/o
         ------------------------------------------------------------------------------
           oct    | 0x0020 |              转换基数为八进制形式                   i/o
         ------------------------------------------------------------------------------
           hex    | 0x0040 |             转换基数为十六进制形式                  i/o
         ------------------------------------------------------------------------------
         showbase | 0x0080 |                输出数据前有0/0x                      o
         ------------------------------------------------------------------------------
        showpoint | 0x0100 |              浮点数输出带有小数点                    o
         ------------------------------------------------------------------------------
        uppercase | 0x0200 |           用大写字母输出十六进制数值                 o
         ------------------------------------------------------------------------------
         showpos  | 0x0400 |               正数前面有“+”号                      o
         ------------------------------------------------------------------------------
        scientfic | 0x0800 |            浮点数输出采用科学表示法                  o
         ------------------------------------------------------------------------------
          fixed   | 0x1000 |            使用定点数形式表示浮点数                  o
         ------------------------------------------------------------------------------
         unitbuf  | 0x2000 |        完成输入操作后立即刷新流的缓冲区              o
         ------------------------------------------------------------------------------
          stdio   | 0x4000 |         完成输入操作后刷新系统的stdout               o
         ------------------------------------------------------------------------------    
       2).使用成员函数设置标志字:
           1.long flags()       //该函数用来返回标志字
           2.long flags(long)   //该函数使用参数更新标志字,返回更新前的标志字
           3.long setf(long setbits,long field)//将field所指定的标志清零,将setbits为1的位置1,返回以前的标志字
           4.long setf(long)  //设置参数所指定的那些标志的位,返回更新前的标志字
           5.long unsetf(long)//该函数用来清除参数所指定的那些标志位的位,返回更新前的标志字
        在ios类中,定义了下面的表态类对象;
           static const long  basefield; //其值为dec/oct/hex
           static const long adjustfield //其值为left/right/internal
           static const long  floatfield //其值为scientific/fixed
        example:  cin.setf(ios::dec,ios::basefield      
    B.格式输出函数:
       1).设置输出数据所占宽度的函数
           1.int width()//该函数返回当前输出数据的宽度
           2.int width(int)//刻函数用来设置当前输出数据的宽度为参数值,并返回更新前的宽度值
       2).填充当前宽度内的填充字符函数
           1.char fill()//该函数用来返回当前所使用的填充字符
           2.char fill(char)//该函数用来设置填充字符为参数值所表示的字符,并返回更新前的填充字符
       3).设置浮点数输出精度函数
           1.int precision()//该函数返回当前浮点数的有效数字的个数
           2.int precision(int)//该函数设置浮点数输出时的有效数字个数,并返回更新前的值。
      注意:float型实数最多提供7位有效数字,double型褛最多提供15位有效数字,long。。。提供19位有效数字
   C.操作子:为了简化操作,提供了一系列操作子,操作子实际上是对象
       --------------------------------------------------------------------
        dec             数值数据采用十进制表示                 i/o
       --------------------------------------------------------------------
        hex             数值数据采用十六进制表示               i/o
       --------------------------------------------------------------------
        oct             数值数据采用八进制表示                 i/o
       --------------------------------------------------------------------
        setbase(int)|  设置数据转换基数为n(n为0,8,10,16),其中0表示缺省基数  i/o
       --------------------------------------------------------------------
        ws           提取空白符                                 i
       --------------------------------------------------------------------
        ends         插入空白符                                 o
       --------------------------------------------------------------------
        flush       刷新与流相关联的缓冲区                      o
       --------------------------------------------------------------------
        resetiosflags(long)     清除参数所指定的标志位         i/o
       --------------------------------------------------------------------
        setiosflags(long)       设置参数所指定的标志位         i/o
       --------------------------------------------------------------------
        setfill(int)            设置填充字符                    o
       --------------------------------------------------------------------
        setsprecision(int)      设置浮点数输出的有效数字个数 |     o
       --------------------------------------------------------------------
        setw(int)               设置输出数据项的域宽            o
       --------------------------------------------------------------------
21. 字符串流:例170开始
      c++提供了两个类:头文件#include"strstrea.h"
         1.ostrstream:其是从ostream派生来的,将不同类型转换为字符串,并存放到数组中.
             ostrstream::ostrstream();//缺省构造函数,它用来建立存储所插入的数据的数组对象;
             ostrstream::ostrstream(char *s,int n,int mode=ios::out);//此构造函数中S是字符指针或字符数组,N是用来指定这个数组最多能存放的字符个数.mode参数给出流式的方式,缺省为out方式,还可选用ate和app方式.
           ostrstream类还提供了如下的成员函数:
             int ostrstream::pcount();//返回流中已插入的字符个数;
             char *ostrstream::str(); //返回标志字符串的数组的指针值;
         2.istrstream:其是从istream派生来的,将文本项转换为变量所需要的内部格式.     
             istrstream::istrstream(char *s);//构造函数中S是一个字符指针或字符数组,使用该串来初始化要创建的流对象
             istrstream::istrstream(char *s,int n);//此构造函数是使用串中前N个字符来构造串对象
22.异常处理
      try{   }
      throw 变量
      catch(形式参数变量){   } //其中形数参数变量只能是一个,且类型不能像函数传递形参那样进行自动转换,必须完全批配
   注意:1.当找不到指导配项时,就用黑认批配项abort()一终止程序               
         2.异常处理的数据类型是公有基类,抛掷异常的数据类型是派生类
         3.异常处理的数据类型是指向公有基类的指针,抛掷异常的数据类型是指向派生类的指针
            catch(基类)总能够捕获throw(派生类对象),所以catch(基类)块总是放在catch(派生类)块的后面,以避免catch(派生类)永远不能捕获异常
posted @ 2009-04-24 19:34 Pencil.C++ 阅读(133) | 评论 (0)编辑 收藏

19.磁盘文件的输入。头文件#include"fstream.h"  //例题从156开始从156开始   &
    1.打开文件:
         a.   fstream outfile;
              outfile.open("f1.txt",ios::out);//其中fstream为系统对文件专用操作类从156开始   &
         b.   ofstream ostream("f1.txt");
              ofstream ostrm;  ostrm.open("f1.txt");//表示打开某个写文件
         c.   ifstream istrm("f2.txt");defstream.h  例题
              ifstream istrm;  istrm.open("f2.txt");//表示打开某个读文件
      -----------------------------------------------------------------------
                  方式名                        用途19.磁盘文件的输入。头文件#inclu
      ----------------------------------------------------------------------
                   in                        以输入方式打开文件
      -----------------------------------------------------------------------19.磁盘文件的输入。头文件#inclu
                   out                       以输出方式打开文件
      -----------------------------------------------------------------------  
            app                       以输出追加方式打开文件defstream.h  例题
      -----------------------------------------------------------------------
                  ate                       文件打开时,文件指针位于文件尾
      -----------------------------------------------------------------------defstream.h  例题
                   trunc              如果文件存在,将其长度截断为零,并清除所有内容,如果文件不存在,则创建新文件
      -----------------------------------------------------------------------
                   binarg              以二进制方式打开文件,缺省时为文本方式nbsp; 1.打开文件:  
      -----------------------------------------------------------------------
                   nocreate           |打开一个已有文件,如该文件不存在,则打开失败
      -----------------------------------------------------------------------从156开始   &
                   noreplace          |如果文件存在,除非设置 ios::ate或ios::app,否则打开失败
      -----------------------------------------------------------------------
                   ios::in |ios::out  |以读和写的方式打开文件defstream.h  例题
      -----------------------------------------------------------------------
                 ios::out|ios::binary |以二进制方式打开文件
      -----------------------------------------------------------------------   &n
                 ios::in|ios::binary  |以二进制方式打开文件
      -----------------------------------------------------------------------
    2. 关闭文件:从156开始   &
              fstream outfile;
              outfile.close();  
    3. 打开文件失败退出程序:用函数abort();退出,在头文件<stdlib.h"defstream.h  例题
    4.判断文件结束函数.example:  infile.eof()
    5.getline(char*,sizeof(s));//读取一串字符
      get()/put()//对文件字符操作,例如outfile.get  defstream.h  例题
    6.随机访问数据文件:
        1)读指针
          istream &istream::seekg(流中位置)//   &n
          istream &istream::seekg(偏移量,参照位置)//参照位置分为:cur=1/beg=0/end=2  input.seekg(-100,ios::cur);
          streampos istream::tellg();//其中streampos定义为long型,它返回一个long型且值为当前指针离文件开头的位置(字节数)
        2)写指针defstream.h  例题
          ostream &ostream::seekp(流中的位置)
          ostream &ostream::seekp(偏移量,参照位置)//参照位置同上
          streampos ostream::tellp();   &n
     注意:读函数中有get(),写函数中有put(),操作读指针用seekg(),而写指针用seekp();write()和read()中的第一个参数必须为(char *),如果不是,一定要强制转换
    7.  while(!cin);//表示输入流有错。
        cin.clear();//原型 void ios::clear(int=0);其用途是将错误状态的标志字中错误标志位清除,重新判断输入。19.磁盘文件的输入。头文件#inclu
        cin.ignor(80,ch);//如果ch='\n',一般表示忽略一行,重新到下一行去输入
        istream &istream::ignore(int n=1,int t=EOF);//跳过输入流中指定数量的字符的函数,t为终止符,一般EOF相当于<ctrl+z>操作
        istream &istream::pubback(char ch)//退回一个字符到输入流的函数,其中ch是指出要退回输入流的字符。
posted @ 2009-04-24 19:34 Pencil.C++ 阅读(157) | 评论 (0)编辑 收藏

12.运算符重载:  &nbs12.运算符重载:
      operator 函数用法:(不能有下列字符:'::','.','*','->','? :')p;   
          1.一般:int class_name::operator <运算符> (形参列表)   (例92)
          2.增量减量运算符:   (例93,94,95,96)
               a.将一个增量运算符重载为前置的成员函数:12.运算符重载:  &nbs
                           int class_name::operator++();
               b.将一个增量运算符重载为后置的成员函数:
                           int class name::operator++(int);12.运算符重载:  &nbs
               c.将一个增量运算符重载为前置的友元函数:
                           int operator ++(class_name&);         
               d.将一个增量运算符重载为前置的友元函数:)    
                           int operator ++(class_name&,int);     
               e.下标运算符:
                           int class_name::operator[](形参)  //只能是非静态成员函数                           operator 函数用法:(不能有下
               f.函数调用运算符: 
                           int class_name::operator()(形参表)//只能是非静态函数,且不可以带有缺省的参数
               g.成员选择运算符:12.运算符重载:  &nbs
                           class_name $/* class_name::operator->();
               h.new delete运算符:
                           void *class_name::operator new(siz_t,<arg_list>);12.运算符重载:  &nbs
                           void *class_name::operator delete(void *,<size_t>);
                   new delete只能被重载为类的成员函数,不能是友元。而且无论是否使用关键字static
                   进行修饰,重载了的new和delete均为类的表态成员函数。p;   
                       对于typedef unsigned size_t;
                   在头文件alloc.h,mem.h,stddef.h,stdio.h,stdlib.h均说明;
               i.友元函数: operator 函数用法:(不能有下
                       可以是一个类的非静态函数,也可以是类的友元函数。
                      {friend complex operator+(complex&,complex&);
                      }; 12.运算符重载:  &nbs
                 以下五种运算符不说明成友元运算符:
                      "=","()","[]","->","type"; 
               j.转换函数: operator 函数用法:(不能有下
                         class_name::operator type();  //type 是任何一个合法的C++的类型名(包括基本数据类型和导出数据类型)以及由关键字const和volatile引出的表达示。)
                                                       //不带任何参数,也无返回值类型,总是返回type的值。只能是类的成员函数,不能说明为友元运算符。
               k.类的赋值运算与运算符重载:列字符:::,.,*,->,? :
                         person & person::operator=(person &p)
                           {dele Name;
                            Name=new char[strlen(p.Name)+1];12.运算符重载:  &nbs
                            strcpy(Name,p.Name);
                            Age=p.Age;
                            Sex=p.Sex;p;   
                            return *this;
                           }
                        典型例题。当用系统自带对象赋值的函数,如果对象里有如 *Name 型的,则赋值后会使两个指针同时指向一个成员元素的地址,当调用析构函数释放时,会释放两次,多释放一次,而产生错误,这个典型例题是用于把一个成员元素复制到另一个对象中,不是单纯移动指针,当调用析构函数时,会释放两次。12.运算符重载:  &nbs
               l.重载函数:系统仅对形参加以区别。
13.虚函数
     一般情况下,指向一个对象的指针,不允许指向另一个对象,但指向基类对象的指针可以指向它的派生类,并可以访问派生类中原基类成员。12.运算符重载:  &nbs
     如果一个函数一旦说明为虚函数,则无论说明它的类被继承了多少层,在每一层中该函数都保持该virturl特性。且可以在派生类中对该函数省略virtual.
     虚函数必须是类的一个成员函数,不能是友元,但它可以是另一个类的友元。虚函数不能是一个静态成员。
     设定绑定方式,使程序具有灵活性,但执行效率低,占用内存多.     operator 函数用法:(不能有下
14.抽象类:纯虚函数
      纯虚函数的一般形式为:virturl 类型名(参数表)=0;抽象类不能申请对象。
15.类属结构:12.运算符重载:  &nbs
       1.函数模板:template <class 模板形参表>                
                返回值类型 函数名(模板函数形参表)
                  {)    
                   函数体;
                  }
             example:p;   
                 template  <class T>
                 void swap(T &.x,T&.y)
                  {T t;列字符:::,.,*,->,? :
                   t=x;x=y;y=t;
                  }
       2.重载函数模板:调用用次序:12.运算符重载:  &nbs
            1)寻找一个完全匹配的函数,找到,调用之。
            2)寻找一个函数模板,将其实例化产生一个匹配的模板函数,找到,调用之。
            3)寻找重载函数中有无通过类型转换后产生参数匹配的函数,若有,调用之。p;   
       3.类模板:template <class 模板形参>
                 class 类模板名
                 {12.运算符重载:  &nbs
                  类体;
                 }
             example:  tempplate <class T>12.运算符重载:  &nbs
                       class stack
                       {private:
                          T *date; 12.运算符重载:  &nbs
                          int top;
                        public:
                          isempty();12.运算符重载:  &nbs
                       }
                       template <class T>
                       {...}   operator 函数用法:(不能有下
16.类模板的友元:
          a.一般的类模板友元函数。
          b.封闭型的类模板友元函数。当用类型参数将类模板实例化为某个具体的模板类时,该类模板所包含的友元函数也将随之实例化。列字符:::,.,*,->,? :
          c.开放型的类模板友元函数。
       例一百二十一。
17.C++的I/O流库 operator 函数用法:(不能有下
    1.  I/O标准流类  
        -----------------------------------------
        c++名字  设备  | C中的名字 | 默认的含义)    
        -----------------------------------------
        cin      键盘  | stdin     | 标准输入
        -----------------------------------------12.运算符重载:  &nbs
        cout     屏幕  | stdout    | 标准输出
        -----------------------------------------
        cerr     屏幕  | stderr    | 标准错误)    
        -----------------------------------------
        clog     | 打印机 | stdprn    打印机
        -----------------------------------------p;   
     2。键盘输入
        cin>>a>>b>>c;  //Ctrl+z终止
        cin.get(char &ch)//从输入流获取一个字符,不忽略空格Ctrl+z终止)    
        cout.put(ch)//输出一个字符       
    EOF//其值为-1,相当于终止符 
        cin.geline(char *buf,int limit,Deline='\n')//buf为一个指针或数组,limit为字符个数,Deline为读取字符指定结束符。作用:从键盘读入一串字符。结束用Ctrl+z.列字符:::,.,*,->,? :
    cin.gcount()//返回getline()刚刚读过的字符个数 
        cin.read(char *buf,int size)//读入指定数目的字符
    cout.write(const char *str,int n)//cout.write("string",strlen("string");则输出全部字符。p;   
    cin.peek()//返回输入流的下一个字符,但是不提取它。
    long(a)//a可以是指针地址,作用,强制转换为十进制数。
    (void*)//ex:char str="abcde";cout<<str;将str为首地址字符串的首地址输出。   列字符:::,.,*,->,? :
18.输入符,提取符重载:<<  >>
     例154 155例题
posted @ 2009-04-24 19:33 Pencil.C++ 阅读(227) | 评论 (0)编辑 收藏

1.              I/O流的常用控制符 1.   
              dec                         置基数为10
              hex                         置基数为16
              oct                         置基数为8; IO流的常用控制符  &n
              setfill(c)                  设填充字符为C
              setprecision(n)             设显示小数精度为n位
              setw(n)                     设域宽为N个字符; IO流的常用控制符  &n
              setiosflags(ios::fixed)     固定的符点显示
              setiosflags(ios::scientific)指数表示
              setiosflags(ios::left)      左对齐; IO流的常用控制符  &n
              setiosflags(ios::right)     右对齐
              setiosflags(ios::skipws)    忽略前导空白
              setiosflags(ios::uppercase) 16进制数大写输出sp;   
              setiosflags(ios::lowercase) 6进制数小写输出  
              setiosflags(ios::showpoint) 显示小数点
              setiosflags(ios::showpos)   正数前面加上正号  &
2.头文件:*iostream.h*    *iomanip.h*   *stdlib.h*
           cout/cin   流的控制符  exit(0)      
3.指针的几种类型: 1.   
  int (*p)();p为指向函数的指针变量,该函数带回一个整形值
  int *p();p为带回一个指针的函数,该指针指向整形数据
  int (**)[n]p为一个指向一个指针变量的指针变量,被指向的指针变量指向一个含n个整形数据的一维数组sp;   
4.构造函数和析构函数特点及其区别:
   a.构造函数可以有任意个形参,还可以重载(多个参数个数不同的函数);但析构函数不能有形参,因为是系统自动调用的.
   b.构造函数不可以任意调用,只准系统调用;而析构函数不仅系统调用,也可以任意调用.                               ; IO流的常用控制符  &n
5.构造函数和析构函数什么时候自动运行?(例61)
          构造函数:一般在定义类对象时自动运行.
          析构函数:如果一个函数中定义了一个对象,则在这个函数运行结束时就执行一次; 1.   
                   当一个对象是使用NEW运算符被动态创建的,在使用DELETE运算符释放它时,DELETE将会自动调用析构函数.
          拷贝初始化构造函数:当用tpoint N(M);语句时调用一次;
                         当对象作为实参向形参传递时,即对形参初始化时执行一次;; IO流的常用控制符  &n
                         当遇到M=return(N);语句,即对M进行初始化时调用一次;

6.this 指针用法:例63中,当程序执行语句list elem(i);时,系统对this指针进行了如下的缺省赋值:this=&list;
                赋值成员函数举例(此例在例63基础上):  &
                      void Assign(linear_list&);//说明语句;
                      void linear_list::Assign(linear_list&p)
                       {if(&p==this); IO流的常用控制符  &n
                           return;
                        nmax=p.nmax;
                        nelem=p.nelem;; IO流的常用控制符  &n
                        list=new int[nmax];
                        for(int i=0;i<nmax;i++)
                           list[i]=p.list[i];  &
                       
7.const,volatile对象和const,volatile成员函数
  格式:const person per/volatile person per;                        1.   
       int func(int) const;/char func(int) volatile;
  说明:1.普通对象既可以访问const对象,又可以访问volatile对象;
       2.const对象只能访问用const修饰的成员函数;sp;   
         volatile对象只能访问用其所长volatile修饰的成员函数;
       3.也可以同时说明为const volatile对象或const volatile成员函数;
         const volatile对象只能访问const volatile成员函数;nbsp;  &nb
         const/volatile对象也能访问const volatile成员函数;
8.不同继承方式的基类和派生类特性
  ------------------------------------------------  &
   继承方式       基类特性        派生类特性
  ------------------------------------------------
                  public          public 1.   
   公有继承       protected       protected
                  private         不可访问
  ------------------------------------------------ 1.   
                  public          private
   私有继承       protected       private
                  private         不可访问  nbsp;  &nb
  ------------------------------------------------
                  public          protected
   保护继承       protected       protected 1.   
                  private         不可访问
  ------------------------------------------------
  A:帮助理解:1)对于公有继承方式:nbsp;  &nb
               a.基类成员对其对象的可见性:公有成员可见,其他不可见。这里保护成员同于私有成员。
               b.基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
               c.基类成员对派生类对象的可见性:公有成员可见,其他成员不可见。 1.   
            所以,在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。
            2) 对于私有继承方式:
               a.基类成员对其对象的可见性: 公有成员可见,其他不可见。nbsp;  &nb
               b.基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见      
               c.基类成员对派生类对象的可见性:所有成员都是不可见的。
            所以,在私有继承时,基类的成员只能由直接派生类访问,而无法再往下继承。; IO流的常用控制符  &n
            3) 对于保护继承方式:
               与私有继承方式相同,两者的区别仅在于对派生类的成员而言,对基类成员有不同的可见性。
 B:帮助理解:1) 公有继承时,水平访问和垂直访问对基类中的公有成员不受限制。; IO流的常用控制符  &n
             2) 私有继承时,水平访问和垂直访问对基类中的公有成员也不能访问。
             3) 保护继承时,对于垂直访问同于公有继承,对于水平访问同于私有继承。
             4) 对于基类中的私有成员,只能被基类中的成员函数和友元函数访问,不能被其他的函数访问。  &
 C:帮助理解:在公有继承时,派生类的成员函数可访问基类中的公有成员和保护成员;派生类的对象仅可访问基类中的公有成员。
9.派生类的构造函数和析构函数:
     派构:  &
         1.一般格式: 派生类名  (派生类构造函数总参数表):基类构造函数(参数表1),子对象名(参数表2)
                          {派生类中数据成员初始化};
         2.调用顺序: a.基类的构造函数。b.子对象类的构造函数(如果有的话). c.派生类构造函数。                           &
10.多继承:是指派生类具有多个基类。
   多继承的构造函数:
                   《派生类名》(总参数表):《基类名1》(参数表1),《基类名2》(参数表2),...nbsp;  &nb
                       {派生类构造函数体}  
11.虚基类:如果基类被声明为虚基类,则重复继承的基类在派生磁对象实例中只好存储一个副本,否则,将出现多个基类成员副本。
   虚基类说明格式如下:  virtual<继承方式><基类名> 1.   
                         class B:virtual public A
  注意:a.如果一个派生类有直接或间接的虚基类,那么派生类的构造函数的成员初始列表中必须列出对虚基类的调用,如果未被列出,则表示使用该基类的缺省构造函数来初始化派生类对象中的虚基类子对象。
        b.虚基类的构造函数先于非虚基类的构造函数调用。nbsp;  &nb
        c.只有建立对象的那么个派生类的构造函数调用虚基类的构造函数,而该派生类的基类中所列出的对这个虚基类的构造函数的调用在执行中被忽略。

posted @ 2009-04-24 19:32 Pencil.C++ 阅读(163) | 评论 (0)编辑 收藏

仅列出标题
共4页: 1 2 3 4