steampower

2006年5月29日

一些链接
一些觉得不错的总结,比较适合中期使用者,懒得贴过来,把链接贴出来好了:

vc 使用总结

编译器处理相关  介绍编译器的编译的过程

使用 HOOK 实现 Outlook Express 工具条 

VC中利用多线程技术实现线程之间的通信

为什么会出现LNK2005
posted @ 2006-05-29 10:20 steapower 阅读(267) | 评论 (0) | 编辑 收藏
 

2006年5月26日

一些零碎的问题(转载及备忘)
  1. MFC中使用全局变量
        对于全局的变量 在一个地方申明 如 ONE.CPP 在另一个地方要用 如 TWO.CPP 那么TWO.CPP中要重新申明一下,关键字就是extern 
  如:
 
  one.cpp
     
int temp;
  two.cpp
     
extern int temp;

 2.c语言的cdecl调用规范是特有的。
 例如有函数: int f(int,...) r = f(a1,a2,a3,a4)
它动作如下:
 1. 调用方,先把参数按从后面到前面的顺序压栈。 --> 为什么这么做?为了实现可变参数。特别是为main和printf所做的工作。 .... 如上面的f,在调用时按a4,a3,a2,a1顺序压栈。即使参数无数个,也不会影响函数的实现。

 2. 调用方,负责清理栈空间 --> 为什么这么做?因为到底压了多少个参数在栈里头,只有调用方才知道。

 3. 返回值,一概放到规定的寄存器中。 --> 为什么这么做?这样可以允许不使用返回值,寄存器不占用存储空间,不用关心内存资源问题。

  小结:使用了cdecl,c语言就可以只关心函数名,而不再关心参数个数,参数类型,函数的返回值问题。因此,一个函数名,仅仅表示了函数的入口,而c语言中的函数原型,仅仅是为了让编译器生成相应的调用代码。 因此,对于一个函数而言,函数原型,爱怎么定义就怎么定义,编译器和链接器都不会怪你;后果就是,如果原型定义有问题,运行结果要么是错的,要么程序甚至系统崩溃。

相关链接 为什么main有多种格式?

常量指针和指针常量

 
char  * const cp; ( * 读成 pointer to )

     cp is a const pointer to char ,亦即指针常量,cp值(cp指向的地址)不可改变,但*cp,也就是cp所指对象能够改变。

const char * p;

char const * p;

     p is a pointer to const char,亦即指向常量的指针,所以p所指的对象不可改变。

void main()

{

 int a = 2;

 int b = 4;

intconst* pa = &a;//常量指针,指针指向常量

 int *const pb = &b;//指针常量,指针本身是常量

pa = &b;//right 常量指针,它所指向的地址可以改变

 *pb = 7;//right 指针常量,它所指向的值可以改变

 //*pa = 7;//error

 //pb = &b;//error

}


posted @ 2006-05-26 20:57 steapower 阅读(254) | 评论 (0) | 编辑 收藏
 

2006年5月17日

VC中常见的错误:


LNK2001错误

  unresolved external symbol “symbol”(不确定的外部“符号”),如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误消息。一般来说,发生错误的原因有两个:

  • 是所引用的函数、变量不存在、拼写不正确或者使用错误;
  • 是可能使用了不同版本的连接库;

  以下是可能产生LNK2001错误的原因:

  一.由于编码错误导致的LNK2001。

  1.不相匹配的程序代码或模块定义(.DEF)文件能导致LNK2001。例如,如果在C++ 源文件内声明了一变量“var1”,却试图在另一文件内以变量“VAR1”访问该变量,将发生该错误。

  2.如果使用的内联函数是在.CPP文件内定义的,而不是在头文件内定义将导致LNK2001错误。

  3.调用函数时如果所用的参数类型同函数声明时的类型不符将会产生LNK2001。

  4.试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001。

  5.要注意函数和变量的可公用性,只有全局变量、函数是可公用的。静态函数和静态变量具有相同的使用范围限制。当试图从文件外部访问任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001。

  函数内声明的变量(局部变量) 只能在该函数的范围内使用。

  C++ 的全局常量只有静态连接性能。这不同于C,如果试图在C++的多个文件内使用全局变量也会产生LNK2001错误。一种解决的方法是需要时在头文件中加入该常量的初始化代码,并在.CPP文件中包含该头文件;另一种方法是使用时给该变量赋以常数。

  二.由于编译和链接的设置而造成的LNK2001

  1.如果编译时使用的是/NOD(/NODEFAULTLIB)选项,程序所需要的运行库和MFC库在连接时由编译器写入目标文件模块, 但除非在文件中明确包含这些库名,否则这些库不会被链接进工程文件。在这种情况下使用/NOD将导致错误LNK2001。

  2.如果没有为wWinMainCRTStartup设定程序入口,在使用Unicode和MFC时将得到“unresolved external on _WinMain@16”的LNK2001错误信息。

  3.使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内,源文件中对“func”的引用,在目标文件里即对“__imp__func” 的引用。如果试图使用静态库LIBC.LIB或LIBCMT.LIB进行连接,将在__imp__func上发
生LNK2001;如果不使用/MD选项编译,在使用MSVCxx.LIB连接时也会发生LNK2001。

  4.使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001。

  5.当编译调试版的应用程序时,如果采用发行版模态库进行连接也会产生LNK2001;同样,使用调试版模态库连接发行版应用程序时也会产生相同的问题。

  6.不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可能包含早先的版本没有的符号和说明。

  7.在不同的模块使用内联和非内联的编译选项能够导致LNK2001。如果创建C++库时打开了函数内联(/Ob1或/Ob2),但是在描述该函数的相应头文件里却关闭了函数内联(没有inline关键字),这时将得到该错误信息。为避免该问题的发生,应该在相应的头文件中用inline关键字标志内联函数。

  8.不正确的/SUBSYSTEM或/ENTRY设置也能导致LNK2001。

  其实,产生LNK2001的原因还有很多,以上的原因只是一部分而已,对初学者来说这些就够理解一阵子了。但是,分析错误原因的目的是为了避免错误的发生。LNK2001错误虽然比较困难,但是只要注意到了上述问题,还是能够避免和予以解决的。
posted @ 2006-05-17 11:03 steapower 阅读(310) | 评论 (0) | 编辑 收藏
 

2006年3月27日

活着
    在武汉待了6年,从本科一直读到研究生。从憧憬到彷徨,从彷徨到失落,从失落到随波逐流。用一句话概括我的状态就是:活着。
    读到一篇外文的散文,作者说自己的一生被三种情绪所左右:
    对世界的好奇,对未知的向往。
    对爱的追求和执着,以及随之而来的痛苦和欢愉。
    生为人类的一种痛苦,为孤独的人痛苦,为无知的人痛苦,为自己痛苦。
    对作者的三种情绪,我深以为是。曾经对世界的一切一切充满好奇,天真的想要了解一切,也曾经幻想突如其来的浪漫的爱情, 那是一片樱花树下凄厉的烂漫,也 曾经寄予自己更多的目标和要求。但是人已老去,那种激情亦不在拥护,现在的我更多的是被为人的痛苦所包围,不愿意面对更多的黑暗,更不愿意化身为阴影中普 通的一员。
      
posted @ 2006-03-27 10:40 steapower 阅读(192) | 评论 (0) | 编辑 收藏
 
MFC框架下的指针的获得(转贴加个人总结)
    VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决。
下面文字主要是个人在编程中指针使用的一些体会,说的不当的地方请指正。
一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,无论是多文档还是单文档,都存在指针获取和操作问题。
下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先一般获得本类(视,文档,对话框都支持)实例指针 this,用this的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的功能。

1) 在View中获得Doc指针
CYouSDIDoc *pDoc=GetDocument();

一个视只能有一个文档。
2) 在App中获得MainFrame指针
CWinApp 中的 m_pMainWnd变量就是MainFrame的指针
也可以:
CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();

3) 在View中获得MainFrame指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;

4) 获得View(已建立)指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
CyouView *pView=(CyouView *)pMain->GetActiveView();
5) 获得当前文档指针
CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();
6) 获得状态栏与工具栏指针
CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
7) 如果框架中加入工具栏和状态栏变量还可以这样
(CMainFrame *)GetParent()->m_wndToolBar;
(CMainFrame *)GetParent()->m_wndStatusBar;
8) 在Mainframe获得菜单指针
CMenu *pMenu=m_pMainWnd->GetMenu();
9) 在任何类中获得应用程序类
用MFC全局函数AfxGetApp()获得。

10) 从文档类取得视图类的指针
我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。
CDocument类提供了两个函数用于视图类的定位:
GetFirstViewPosition()和GetNextView()
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;

注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。
GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一个POSITION类型值), GetNextView()有两个功能:返回下一个视图类的指针以及用引用调用的方式来改变传入的POSITION类型参数的值。很明显,在Test程序 中,只有一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定义一个POSITION结构变量来辅助操作):
CTestView* pTestView;
POSITION pos=GetFirstViewPosition();
pTestView=GetNextView(pos);
这样,便可到了CTestView类的指针pTestView.执行完几句后,变量pos=NULL,因为没有下一个视图类,自然也没有下一个视图类的 POSITION.但是这几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所 有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如:
pView->IsKindOf(RUNTIME_CLASS(CTestView));
即可检查pView所指是否是CTestView类。

有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:
CView* CTestDoc::GetView(CRuntimeClass* pClass)
{
    CView
* pView;
    POSITION pos
=GetFirstViewPosition();

    
while(pos!=NULL){
        pView
=GetNextView(pos);
        
if(!pView->IsKindOf(pClass))
        
break;
    }

    
if(!pView->IsKindOf(pClass)){
        AfxMessageBox(
"Connt Locate the View.\r\n http://www.VCKBASE.com");
        
return NULL;
    }

    
return pView;
}



其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种可能:

1.pos为NULL,即已经不存在下一个视图类供操作;
2.pView已符合要求。

1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此pos是pView的下一个 视图类的POSITION,完全有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一个视图类时就如引。因此需采用 两次判断。
使用该函数应遵循如下格式(以取得CTestView指针为例):
CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));
RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为CRuntimeClass为指针。
至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦。

3.从一个视图类取得另一视图类的指针 综合1和2,很容易得出视图类之间互相获得指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数:
(假设要从CTestAView中取得指向其它视图类的指针)
CView* CTestAView::GetView(CRuntimeClass* pClass)
{
CTestDoc* pDoc=(CTestDoc*)GetDocument();
CView* pView;
POSITION pos=pDoc->GetFirstViewPosition();
while(pos!=NULL){
pView=pDoc->GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.");
return NULL;
}

return pView;
}
这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档类成员函数。
有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如下:
CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));
11)对于单文档中也可以加入多个文档模板,但是一般的开发就使用MDI方式开发多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清楚,请查阅MSDN,(以下四个内容(11、12、13、14)来源:http://sanjianxia.myrice.com/vc/vc45.htm)

可以用CWinApp::GetFirstDocTemplatePostion获得应用程序注册的第一个文档模板的位置;
利用该值来调用CWinApp::GetNextDocTemplate函数,获得第一个CDocTemplate对象指针。
POSITION GetFirstDocTemplate( ) const; 
CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;
第二个函数返回由pos 标识的文档模板。POSITION是MFC定义的一个用于迭代或对象指针检索的值。通过这两个函数,应用程序可以遍历整个文档模板列表。如果被检索的文档模板是模板列表中的最后一个,则pos参数被置为NULL。

12)一个文档模板可以有多个文档,每个文档模板都保留并维护了一个所有对应文档的指针列表。
用CDocTemplate::GetFirstDocPosition函数获得与文档模板相关的文档集合中第一个文档的位置,并用POSITION值作为CDocTemplate::GetNextDoc的参数来重复遍历与模板相关的文档列表。函数原形为:
viaual POSITION GetFirstDocPosition( ) const = 0; 
visual CDocument *GetNextDoc(POSITION & rPos) const = 0;
如果列表为空,则rPos被置为NULL.

13)在文档中可以调用CDocument::GetDocTemplate获得指向该文档模板的指针。函数原形如下:
CDocTemplate * GetDocTemplate ( ) const; 
如果该文档不属于文档模板管理,则返回值为NULL。

14)一个文档可以有多个视。每一个文档都保留并维护一个所有相关视的列表。CDocument::AddView将一个视连接到文档上,将该视加入到文 档相联系的视的列表中,并将视的文档指针指向该文档。当有File/New、File/Open、Windows/New或Window/Split的命 令而将一个新创建的视的对象连接到文档上时, MFC会自动调用该函数,框架通过文档/视的结构将文档和视联系起来。当然,程序员也可以根据自己的需要调用该函数。
Virtual POSITION GetFirstViewPosition( ) const; 
Virtual CView * GetNextView( POSITION &rPosition) cosnt;
应用程序可以调用CDocument::GetFirstViewPosition返回与调用文档相联系的视的列表中的第一个视的位置,并调用 CDocument::GetNextView返回指定位置的视,并将rPositon的值置为列表中下一个视的POSITION值。如果找到的视为列表 中的最后一个视,则将rPosition置为NULL.

15)从一个视图类取得另一视图类的指针
这个应用在多视的应用程序中很多见,一般如果自己在主程序或者主框架中做好变量记号,也可以获得,还有比较通用的就是用文档类作中转,以文档类的视图遍历定位,取得另一个视图类。这个功能从本文第10项中可以得到。
posted @ 2006-03-27 10:36 steapower 阅读(808) | 评论 (0) | 编辑 收藏
 
仅列出标题  
 
<2025年5月>
日一二三四五六
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

 导航

  • C++博客
  • 首页
  • 发新随笔
  • 发新文章
  • 联系
  • 聚合
  • 管理

 统计

  • 随笔: 5
  • 文章: 0
  • 评论: 0
  • 引用: 0

常用链接

  • 我的随笔
  • 我的评论
  • 我参与的随笔

留言簿(1)

  • 给我留言
  • 查看公开留言
  • 查看私人留言

随笔分类

  • C++语言 (rss)
  • MFC框架(4) (rss)
  • OpenGL 和Open invnetor 开发 (rss)
  • 个人随笔(1) (rss)
  • 项目经验 (rss)

随笔档案

  • 2006年5月 (3)
  • 2006年3月 (2)

网友的blog

  • Jerry Cat 的blog
  • zhanghl的blog

搜索

  •  

最新评论

阅读排行榜

  • 1. MFC框架下的指针的获得(转贴加个人总结)(808)
  • 2. VC中常见的错误:(310)
  • 3. 一些链接(267)
  • 4. 一些零碎的问题(转载及备忘)(254)
  • 5. 活着(192)

评论排行榜

  • 1. MFC框架下的指针的获得(转贴加个人总结)(0)
  • 2. 活着(0)
  • 3. VC中常见的错误:(0)
  • 4. 一些零碎的问题(转载及备忘)(0)
  • 5. 一些链接(0)

Powered by: 博客园
模板提供:沪江博客
Copyright ©2025 steapower