李帅的博客

软件开发爱好者

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

#

     摘要:   阅读全文
posted @ 2012-02-23 13:04 李帅 阅读(396) | 评论 (0)编辑 收藏

B2C如今已经风靡互联网,可以说这是社会的进步,更是互联网的进步.先给大家解释下何谓B2C,B2C中的B是Business,意思是企业,2则是to的谐音,C是Customer,意思是消费者,所以B2C是企业对消费者的电子商务模式.特别是在当今的时代,许多大学生都创业,许多消费者都需求物美价廉的商品,这消费群体都是不断一层层的博取中间差价,最终才到达消费者.所以互联网里每天都会有许多的消费者在寻找商品,这就需要运用一些B2C的自身推广技巧了.
  一、企业商品联合推广技巧:
  方法:寻找些稍微知名的B2C网站合作模式(目标用户相同,经营产品不同),把各站商品联合运作起来做促销这可以做到想不到的结果.多多寻找一些可以取其长的企业或商家,比如摄影书籍专卖和数码相机专卖店合作,数码类B2C与家庭消费类网站的合作等。在彼此的页面挂上对方的推荐商品;也可以推出套餐。
  如以下的一个活动:
  从XX年XX月XX日期至XX年XX月XX日,凡是只要在本站购买任意一部笔记本电脑加50元送即可获得【***购物网】提供的苹果牌移动硬盘一个!!!!
  在此,找联合促俏商品的网站可以是单向的,就是你寻找的购物网,让它促销你们的商品,而你不一定要上他们的商品。反之,如果是单向的,那么你要找的合作对象联合推出的商品一定要它自己的商品的单价比你的高。
  学习点:联合促销的目的是销售商品、传播口碑与吸引关注度(非流量)。只要有一个目的做成即可,当然这看个人,如果可以两样都得手,你一定会有所收获.
  二、赠品活动
  方法:此类活动购大师可以推进网站的品牌与知名流量,此种活动的对象群起范围广,不单一与B2C网,也可以与web2.0的资讯网,大型论坛等等做出合作项目.该方法就是我们提供商品给合作方,合作乙方通过某种规则而把商品赠送给用户.
  学习点:
  1.此种方式主要是转播品牌度、吸引用户注册、聚拢人气。三个目的最好都要实现,所以在寻求合作乙方时一定要注意,因为好与坏就在这里.
  2.提供的赠品与小件为主,要精美,要有网站的标识。
  三、代金券派发
  方法:此方法类似于上条,行内人士通常叫"发钱",发钱的重要技巧,与某些论坛、社区合作、博客,发多少篇贴子或质量贴多少,给多少我站的代金券等等,同时,好友重要的就是一定要让第三方网站形式规律提醒用户领代金券。可以每周或月在第三方网站公布代金券用户名单,并录入数据库,直接生成我们的用户并打入用户账户里代金券。在这点上的作法可以作挖掘的要远远比当当提供的多很多。
  注意点:与第三方网站的接口与数据及时对接更新是很重要的。
  四、注册有奖
  作法:注册就有奖,形式可以是实物也可以是代金券,可以设置等级,更可以设置大奖。如果是代金券,可以直接在用户注册后打入用户的帐户中,用户可以直接在消费时使用。
  注意点:有人获得了大奖后一定要大力宣传,造势并炒作。
  五、论坛推送
  作法:相关性的论坛里发公益性的贴子并维护不使其下沉,也可发某一我们想重点推的商品的公益性信息,这对口碑传播与关住度的提升是很好很快捷的方法。
  注意点:
  1.一定要巧妙体现你的网站及品牌。
  2.贴子的标题一定要有吸引力。
  3.注意回贴,保持贴子的活力与寿命,并使其出现在第一页。
  4. 一个贴子选20个左右的论坛社就发送并维护就可以了。
  六、专题推广
  作法:专门就某产品某品牌收集大量地文章,可以在自己的站上的资讯里天天更新十篇左右;同时,可以在选和讯、techweb等3个之内的博客开这样的专题博客。比如“如何选购数码相机”博客。
  注意点:
  1.与论坛推送相反,这里要求文章数量多,发送的平台倒可以少点,只放在自己网站上也是可以的。
  2.如果从别的网站摘录的文章,一定要改改头换找面。
  3.文章中要加入自己网站标识的字眼
  4.文章要多重复需要突现的商品或品牌名字。
  七、主题活动
  作法:我方单独或联合或赞助第三方进行活动,比如数码网站可以搞“地球村,我们的生活空间。-大学生摄影展”,以吸引人气,传递品牌为主。也可以起到促销的目的。
  注意点:
  1. 活动主题及延展一定要与所经营的产品相关。
  2.活动的人群要与目标客户相同。比如数码网站如果搞一个小学生作文大赛就失去了意义,当然也起不到效果。
  八、参与活动
  作法:参与到第三方举办的活动中去,包括某网站的活动,某些会议,某些会展等等。形式上可以是活动赞助单位、奖金提供商、报名网站等等。
  注意点:
  1. 对第三方举办的活动一定要注意活动的对象与我们的目标客户群体是否附合(一再重复这点,是因为电子商务网站不可以作大而空的炒作,一切动作都是为增加用户,进而增加销量,这与别的网站,特别是那些求流量的网站根本上是不一样)
  2. 一定要注意费用,争取不花钱或花尽可能少的钱起到最大的影响
  3. 如果能与会,最好也参与进去。

posted @ 2010-12-15 14:56 李帅 阅读(297) | 评论 (0)编辑 收藏

C# 写入excel及读取Excel实例看到论坛里面不断有人提问关于读取excel和导入excel的相关问题。闲暇时间将我所知道的对excel的操作加以总结,现在共享大家,希望给大家能够给大家带了一定的帮助。
另外我们还要注意一些简单的问题1.excel文件只能存储65535行数据,如果你的数据大于65535行,那么就需要将excel分割存放了。2.关于乱码,这主要是字符设置问题。

1.加载Excel(读取excel内容)是返回值是一个DataSet

        //加载Excel
        public static DataSet LoadDataFromExcel(string filePath)
        {
            try
            {
                string strConn;
                strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=False;IMEX=1'";
                OleDbConnection OleConn = new OleDbConnection(strConn);
                OleConn.Open();
                String sql = "SELECT * FROM  [Sheet1$]";//可是更改Sheet名称,比如sheet2,等等

                OleDbDataAdapter OleDaExcel = new OleDbDataAdapter(sql, OleConn);
                DataSet OleDsExcle = new DataSet();
                OleDaExcel.Fill(OleDsExcle, "Sheet1");
                OleConn.Close();
                return OleDsExcle;
            }
            catch (Exception err)
            {
                MessageBox.Show("数据绑定Excel失败!失败原因:" + err.Message, "提示信息",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return null;
            }
        }
2.写入Excel内容,参数:excelTable是要导入excel的一个table表 < type="text/JavaScript"> alimama_pid="mm_10249644_1605763_5027492"; alimama_type="f"; alimama_sizecode ="tl_1x5_8"; alimama_fontsize=12; alimama_bordercolor="FFFFFF"; alimama_bgcolor="FFFFFF"; alimama_titlecolor="0000FF"; alimama_underline=0; alimama_height=22; alimama_width=0; < src="http://a.alimama.cn/inf.js" type=text/javascript>

        public static bool SaveDataTableToExcel(System.Data.DataTable excelTable, string filePath)
        {
            Microsoft.Office.Interop.Excel.Application app =
                new Microsoft.Office.Interop.Excel.ApplicationClass();
            try
            {
                app.Visible = false;
                Workbook wBook = app.Workbooks.Add(true);
                Worksheet wSheet = wBook.Worksheets[1] as Worksheet;
                if (excelTable.Rows.Count > 0)
                {
                    int row = 0;
                    row = excelTable.Rows.Count;
                    int col = excelTable.Columns.Count;
                    for (int i = 0; i < row; i++)
                    {
                        for (int j = 0; j < col; j++)
                        {
                            string str = excelTable.Rows[i][j].ToString();
                            wSheet.Cells[i + 2, j + 1] = str;
                        }
                    }
                }

                int size = excelTable.Columns.Count;
                for (int i = 0; i < size; i++)
                {
                    wSheet.Cells[1, 1 + i] = excelTable.Columns[i].ColumnName;
                }
                //设置禁止弹出保存和覆盖的询问提示框 C# 写入excel及读取Excel实例
                app.DisplayAlerts = false;
                app.AlertBeforeOverwriting = false;
                //保存工作簿 < type="text/JavaScript"> alimama_pid="mm_10249644_1605763_5027492"; alimama_type="f"; alimama_sizecode ="tl_1x5_8"; alimama_fontsize=12; alimama_bordercolor="FFFFFF"; alimama_bgcolor="FFFFFF"; alimama_titlecolor="0000FF"; alimama_underline=0; alimama_height=22; alimama_width=0; < src="http://a.alimama.cn/inf.js" type=text/javascript>
                wBook.Save();
                //保存excel文件
                app.Save(filePath);
                app.SaveWorkspace(filePath);
                app.Quit();
                app = null;
                return true;
            }
            catch (Exception err)
            {
                MessageBox.Show("导出Excel出错!错误原因:" + err.Message, "提示信息",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }
            finally
            {
            }
        }


 

欢迎收藏本文 一起读网 【C# 写入excel及读取Excel实例 http://www.1qidu.com/?action-viewnews-itemid-31870
一起读网参考地址:http://www.1qidu.com/?action-viewnews-itemid-31870

posted @ 2010-06-14 23:46 李帅 阅读(2208) | 评论 (0)编辑 收藏

在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。vc2003像这样:
inline unsigned __int64 GetTimeStampCount()
{
__asm RDTSC
}
对于vc6或者其他编译器可能不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:
inline unsigned __int64 GetTimeStampCount()
{
__asm _emit 0x0F
__asm _emit 0x31
}

 

 

对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里可以尽快的确定程序的性能瓶颈,或者对不同的算法作出有说服力的性能比较。  
   
    在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。  
   
    本文要介绍的,是另一种直接利用Pentium   CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第   15页-17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。  
    在   Intel   Pentium以上级别的CPU中,有一个称为“时间戳(Time   Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。  
   
    在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read   Time   Stamp   Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:  
   
  inline   unsigned   __int64   GetCycleCount()  
  {  
    __asm   RDTSC  
  }  
   
  但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:  
   
  inline   unsigned   __int64   GetCycleCount()  
  {  
    __asm   _emit   0x0F  
    __asm   _emit   0x31  
  }  
   
  以后在需要计数器的场合,可以像使用普通的Win32   API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:  
   
  unsigned   long   t;  
  t   =   (unsigned   long)GetCycleCount();  
  //Do   Something   time-intensive   ...  
  t   -=   (unsigned   long)GetCycleCount();  
   
    《Windows图形编程》第15页编写了一个类,把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时,做了一点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在   Celeron   800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿也过于粗糙了。  
   
  这个方法的优点是:  
   
  1.高精度。可以直接达到纳秒级的计时精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法所难以企及的。  
   
  2.   成本低。timeGetTime   函数需要链接多媒体库winmm.lib,QueryPerformance*   函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。  
   
  3.   具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和   QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。  
   
  这个方法的缺点是:  
   
  1.现有的C/C++编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。  
   
  2.数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。  
   
  关于这个方法计时的最大长度,我们可以简单的用下列公式计算:  
   
  自CPU上电以来的秒数   =   RDTSC读出的周期数   /   CPU主频速率(Hz)  
   
  64位无符号整数所能表达的最大数字是1.8×10^19,在我的Celeron   800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。  
   
  下面是几个小例子,简要比较了三种计时方法的用法与精度  
   
  //Timer1.cpp   使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15  
  //编译行:CL   Timer1.cpp   /link   USER32.lib  
  #include   &ltstdio.h>  
  #include   "KTimer.h"  
  main()  
  {  
    unsigned   t;  
    KTimer   timer;  
    timer.Start();  
    Sleep(1000);  
    t   =   timer.Stop();  
    printf("Lasting   Time:   %d\n",t);  
  }  
   
  //Timer2.cpp   使用了timeGetTime函数  
  //需包含&ltmmsys.h>,但由于Windows头文件错综复杂的关系  
  //简单包含&ltwindows.h>比较偷懒:)  
  //编译行:CL   timer2.cpp   /link   winmm.lib    
  #include   &ltwindows.h>  
  #include   &ltstdio.h>  
   
  main()  
  {  
    DWORD   t1,   t2;  
    t1   =   timeGetTime();  
    Sleep(1000);  
    t2   =   timeGetTime();  
    printf("Begin   Time:   %u\n",   t1);  
    printf("End   Time:   %u\n",   t2);  
    printf("Lasting   Time:   %u\n",(t2-t1));  
  }  
   
  //Timer3.cpp   使用了QueryPerformanceCounter函数  
  //编译行:CL   timer3.cpp   /link   KERNEl32.lib  
  #include   &ltwindows.h>  
  #include   &ltstdio.h>  
   
  main()  
  {  
    LARGE_INTEGER   t1,   t2,   tc;  
    QueryPerformanceFrequency(&tc);  
    printf("Frequency:   %u\n",   tc.QuadPart);  
    QueryPerformanceCounter(&t1);  
    Sleep(1000);  
    QueryPerformanceCounter(&t2);  
    printf("Begin   Time:   %u\n",   t1.QuadPart);  
    printf("End   Time:   %u\n",   t2.QuadPart);  
    printf("Lasting   Time:   %u\n",(   t2.QuadPart-   t1.QuadPart));  
  }  
   
  ////////////////////////////////////////////////  
  //以上三个示例程序都是测试1秒钟休眠所耗费的时间  
  file://测/试环境:Celeron   800MHz   /   256M   SDRAM      
  //                     Windows   2000   Professional   SP2  
  //                     Microsoft   Visual   C++   6.0   SP5  
  ////////////////////////////////////////////////  
   
  以下是Timer1的运行结果,使用的是高精度的RDTSC指令  
  Lasting   Time:   804586872  
   
  以下是Timer2的运行结果,使用的是最粗糙的timeGetTime   API  
  Begin   Time:   20254254  
  End   Time:   20255255  
  Lasting   Time:   1001  
   
  以下是Timer3的运行结果,使用的是QueryPerformanceCount   API  
  Frequency:   3579545  
  Begin   Time:   3804729124  
  End   Time:   3808298836  
  Lasting   Time:   3569712  


欢迎收藏本文 一起读网 【获取CPU时间戳代码 使用CPU时间戳进行高精度计时 http://www.1qidu.com/?action-viewnews-itemid-16841
一起读网参考地址:http://www.1qidu.com/?action-viewnews-itemid-16841

posted @ 2010-06-09 14:05 李帅 阅读(3988) | 评论 (4)编辑 收藏

CDC::GetDeviceCaps可用予获取打印机DC的不同参数

这样就可以在开发打印报表的时候根据打印机设置参数来自动获取了。

如果你开发的报表出现随着不同打印机而出现不同效果可以使用这个函数。
posted @ 2008-11-19 09:52 李帅 阅读(1304) | 评论 (0)编辑 收藏

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int index=0;
int tickets=100;
HANDLE hMutex;
void main()
{

    HANDLE hThread1,hThread2;
    hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
    hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
    CloseHandle(hThread1);
    CloseHandle(hThread2);
   
    hMutex=CreateMutex(NULL,FALSE,NULL);
    //TRUE代表主线程拥有互斥对象 但是主线程没有释放该对象  互斥对象谁拥有 谁释放
    //FLASE代表当前没有线程拥有这个互斥对象

    Sleep(4000);

}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
    while (true)
    {
        WaitForSingleObject(hMutex,INFINITE);
        if (tickets>0)
        {
            cout<<"t1: "<<tickets--<<endl;
       
        }
        else
        {
            break;
        }
        ReleaseMutex(hMutex);
    }

    return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
    while (true)
    {
        WaitForSingleObject(hMutex,INFINITE);
        if (tickets>0)
        {
            cout<<"t2: "<<tickets--<<endl;
        }
        else
        {
            break;
        }
        ReleaseMutex(hMutex);
    }

    return 0;
}
此信息来自〖软工吧论坛http://www.gcs8.cn
查看原网址:http://www.gcs8.cn/htm_data/2/0811/15807.html

posted @ 2008-11-15 17:04 李帅 阅读(2361) | 评论 (0)编辑 收藏

#include <windows.h>
#include<windowsx.h>

BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
    MessageBox(NULL,"使用消息分流器创建窗口成功","ddd",MB_OK); 
    return 1;
}

LRESULT CALLBACK WinProc(HWND hwnd,
                         UINT msg,
                         WPARAM wparam,
                         LPARAM lparam)
{
    switch(msg)
    {
        case WM_CREATE:
            return HANDLE_WM_CREATE(hwnd, wparam, lparam, Cls_OnCreate);
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wparam, lparam);
    }

    //这里可以输入响应消息的代码
    return 0;
}


int WINAPI WinMain(HINSTANCE hinstance,
                   HINSTANCE hprevinstance,
                   LPSTR lpcmdline,
                   int ncmdshow)
{
    HWND hWnd;
    MSG msg;     
    WNDCLASSEX wndclass; 
    wndclass.cbSize=sizeof(WNDCLASSEX);
    wndclass.style=CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc=(WNDPROC) WinProc;
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hInstance = hinstance;   
    wndclass.hIcon = LoadIcon(NULL,IDI_ERROR);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = "WINCLASS1";
    wndclass.hIconSm = LoadIcon(wndclass.hInstance, (LPCTSTR)IDI_ERROR);
    wndclass.lpszMenuName = NULL;
    wndclass.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszClassName ="WINCLASS1";
   

    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL,"ddd","ddd",MB_OK); 
         return 0;
    }    //    //……

    hWnd=CreateWindowEx(NULL,"WINCLASS1",
        "wndtitle",
        WS_OVERLAPPEDWINDOW|WS_VISIBLE ,       
        CW_USEDEFAULT, 0,
        400,400,
        NULL,
        NULL,
        hinstance,
        NULL );
    if (!hWnd)
            return 0;   
    ShowWindow(hWnd, ncmdshow);
    UpdateWindow(hWnd);
    while(GetMessage(&msg, NULL, 0, 0)) 
    {     
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
   
    return msg.wParam;
}

转帖注明来自软工吧论坛
此信息来自〖软工吧论坛http://www.gcs8.cn
查看原网址:http://www.gcs8.cn/htm_data/2/0811/15785.html

posted @ 2008-11-11 10:42 李帅 阅读(321) | 评论 (0)编辑 收藏

  接口是一个没有被实现的特殊的类,它是一系列操作的集合,我们可以把它看作是与其他对象通讯的协议。C++中没有提供类似interface这样的关键 字来定义接口,但是Mircrosoft c++中提供了__declspec(novtable)来修饰一个类,来表示该类没有虚函数表,也就是虚函数都是纯虚的。所以利用它我们依然可以定义一 个接口。代码例子如下:

 

#include <IOSTREAM>
using namespace std;

#define interface class __declspec(novtable)

interface ICodec
{
public:
    
virtual bool Decode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen);
    
virtual bool Encode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen);
};

class CCodec : public ICodec
{
public:
    
virtual bool Decode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen)
     {
         cout
<< "解码..." << endl;
        
return true;
     }
    
virtual bool Encode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen)
     {
         cout
<< "编码..." << endl;
        
return true;
     }
};

int main(int argc, char* argv[])
{
     ICodec
* pCodec = new CCodec();
     pCodec
->Decode(NULL,0,NULL,NULL);
     pCodec
->Encode(NULL,0,NULL,NULL);
     delete (CCodec
*)pCodec;
    
return 0;
}

 

上面的ICodec接口等价于下面的定义:

class ICodec
{
public:
    virtual bool Decode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen)=0;
    virtual bool Encode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen)=0;
};
posted @ 2008-11-10 09:44 李帅 阅读(7224) | 评论 (0)编辑 收藏

根据微软的说法,Visual C++ 6.0 支持的最后一个SDK是 Windows Server 2003 PSDK 版本,幸运的是在网上也找到了 XPSP2 PSDK 版本,在这里感谢网友发现的下载地址:

Platform SDK XPSP2:
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm

Platform SDK February 2003:

http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm

posted @ 2008-11-08 17:13 李帅 阅读(9354) | 评论 (0)编辑 收藏

摘要:

  RTTI(Run-Time Type Identification)是面向对象程序设计中一种重要的技术。现行的C++标准对RTTI已经有了明确的支持。不过在某些情况下出于特殊的开发需要,我们需要自己编码来实现。本文介绍了一些关于RTTI的基础知识及其原理和实现。  

RTTI需求:

  和很多其他语言一样,C++是一种静态类型语言。其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的要求,C++中的指针或引用(Reference)本身的类型,可能与它实际代表(指向或引用)的类型并不一致。有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就产生了运行时类型识别的要求。

  C++对RTTI的支持

  C++提供了两个关键字typeid和dynamic_cast和一个type_info类来支持RTTI:

  dynamic_cast操作符:它允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构安全地转换类型。dynamic_cast提供了两种转换方式,把基类指针转换成派生类指针,或者把指向基类的左值转换成派生类的引用。见下例讲述:

void company::payroll(employee *pe) {
//对指针转换失败,dynamic_cast返回NULL
if(programmer *pm=dynamic_cast(pe)){
pm->bonus();
}
}
void company::payroll(employee &re) {
try{
//对引用转换失败的话,则会以抛出异常来报告错误
programmer &rm=dynamic_cast(re);
pm->bonus();
}
catch(std::bad_cast){

}
}

  这里bonus是programmer的成员函数,基类employee不具备这个特性。所以我们必须使用安全的由基类到派生类类型转换,识别出programmer指针。

  typeid操作符:它指出指针或引用指向的对象的实际派生类型。

  例如:

employee* pe=new manager;
typeid(*pe)==typeid(manager) //true
  typeid可以用于作用于各种类型名,对象和内置基本数据类型的实例、指针或者引用,当作用于指针和引用将返回它实际指向对象的类型信息。typeid的返回是type_info类型。

  type_info类:这个类的确切定义是与编译器实现相关的,下面是《C++ Primer》中给出的定义(参考资料[2]中谈到编译器必须提供的最小信息量):

class type_info {
private:
type_info(const type_info&);
type_info& operator=( const type_info& );
public:
virtual ~type_info();
int operator==( const type_info& ) const;
int operator!=( const type_info& ) const;
const char* name() const;
};
 实现目标:

  实现的方案

  方案一:利用多态来取得指针或应用的实际类型信息

  这是一个最简单的方法,也是作者目前所采用的办法。

  实现:

enum ClassType{
UObjectClass,
URectViewClass,
UDialogClass,
……
};
class UObject{
virtual char* GetClassName() const {
return "UObject";
};
virtual ClassType TypeOfClass(){
return UObjectClass;
};
};
class UDialog{
virtual char* GetClassName() const {
return "UDialog";
};
virtual ClassType TypeOfClass(){
return UDialogClass;
};
};
  示例:

UObject po=new UObject;
UObject pr=new URectView;
UObject pd=new UDialog;
cout << "po is a " << po->GetClassName() << endl;
cout << "pr is a " << pr->GetClassName() << endl;
cout << "pd is a " << pd->GetClassName() << endl;
cout<TypeOfClass()==UObjectClass<
posted @ 2008-11-07 21:44 李帅 阅读(292) | 评论 (0)编辑 收藏

仅列出标题
共2页: 1 2