微信公众号 
图码生活

每天发布有五花八门的文章,各种有趣的知识等,期待您的订阅与参与
电脑报 1992-2001 十年文章全集
电脑报 1992-2001 十年文章全集
包含从 1992 年 - 2001 年间,两万余篇期刊文章,查询最少输入两个字符
随便看看
读取中
读取中
标题C++Builder 5.0编程指南(1)
栏目附录
作者木子
发布2001年60期
  一、IDE界面介绍
  打开BCB总是出现下面的四个窗口,并且默认创建一个可以立即执行的空应用程序,这个程序只有一个和窗口设计界面一样的窗口。(

)
  1. 对象观察窗口(Object Inspector)
  浏览和修改对象的属性(Properties)和事件(Events)。打开查看窗口的快捷键是F11,
   每个对象都有特定的属性和事件,我们将在后面做介绍(

)。
  2. 代码编辑窗口
  (

)
  代码窗口左边的代码浏览器,列出了代码结构,可以通过它快速定位到特定的代码段。代码编辑器具有很强的自动感应功能,只要程序员键入“->”或者“.”符号,立即就显示出成员变量和成员函数的索引,极大提高了代码的书写效率和准确率,使用“Ctrl+空格”组合键也相同的功能。可是在中文Windows系统下“Ctrl+空格”是打开默认中文输入法,这就要在控制面板中的输入法设定中修改热键了。同样,在编写调用某个函数的代码中键入左括号,编辑器将提示函数的参数名和类别,此功能的组合键是“Ctrl+Shift+空格”。
  3.BCB5.0的主菜单和工具栏按钮
  BCB的全部功能都能在主菜单中找到相应的菜单项。下面作一个简单介绍:
  (1)File菜单
  (

)
  创建项目的选择窗口:
  包含各种类型的程序单元及一些对象创建向导,New页面包含最常用的项目:
  Application:创建一个新的工程,包含一个窗口和窗口的单元文件(.cpp和.h);
  Batch File:创建扩展名为.bat的批处理文件;
  Component:打开组件创建向导;
  Console Wizard:打开控制台程序创建向导;
  Cpp File:添加一个.cpp文件;
  Data Module:创建一个新的数据模块;
  DLL Wizard:打开DLL(动态连接库)创建向导;
  Form:添加一个空白窗口到当前工程;
  Frame:创建一个组件框架;
  Header File:添加一个头文件;
  Library:创建一个库;
  Package:创建一个组件包,可以封装方法并将包中组件安装到BCB的组件栏中;
  Project Group:创建一个新的工程组;
  Remote Data Module:创建一个远程数据模块;
  Report:创建数据报表;
  Resource DLL Wizard:打开创建资源DLL的向导;
  Text:新建一个文本文件;
  Thread Object:在当前工程中创建一个线程;
  Unit:添加一个单元(包含一个.cpp文件和一个.h文件)。
  (2)Edit菜单
  (

)
  (3)Search菜单
  (

)
  (4)View菜单
  (

)
  (5)Project菜单
  (

)
  (6)Run菜单
  (

)
  (7)Component菜单
  (

)
  (8)Database菜单
  (

)
  (9)Tools菜单
  (

)
  (10)Help菜单
  BCB带有非常详尽的Help文本,还有非常详细的WinAPI函数文档,在IDE的任何位置按F1键都可以找到相关的资料。
  二、界面设计
  大多数Windows下的应用程序是由Windows提供的基本元素组成,例如应用程序的窗口、按钮或者是菜单。BCB为我们提供了大量的窗口、按钮、文字输入框等,它们就是BCB中的组件。每个组件都由自己特定的功能,程序员只用关注组件具有什么功能、能够实现什么效果,而不必去考虑这个组件是怎样制作,或者它是由什么制作。这样我们编写程序就像搭积木一样,一块一块的将零散的部件通过我们的代码就连接成为一个整体。
  在这里我们首先了解怎样将BCB提供的组件添加到程序的窗口上。
  组件分为可视组件和不可视组件:可视组件在工程设计或者运行阶段是可以显示的,如按钮、窗口等;不可视组件只是提供某种功能的实现而没有可视的界面,如对话框组件。
  在组件栏中选择一个组件(鼠标单击),然后在设计界面的窗口中用鼠标拖出组件的大小,或者双击组件栏上组件的图标,按组件默认大小和位置添加到设计窗口。同时组件也支持复制、粘贴等操作,粘贴的组件和复制的组件有相近的属性。
  1.调整组件的位置
  调整组件位置有很多的技巧,可以用鼠标拖动,也可以在属性编辑窗口中调整组件的位置属性,也可以使用Ctrl+上、下、左、右方向键,或者是Ctrl+Shift+方向键,或者使用Edit菜单中的Align(对齐)功能来实现。
  为了避免误操作改变组件的位置,可以在Edit菜单中选择Lock Controls功能,这时候就只能用修改属性和菜单中的调整功能了。
  2.选择组件
  可以用鼠标框线、Shift或者Ctrl键加鼠标单击组件的方式一次选择多个组件进行控制。在设计窗口的空白处单击鼠标左键不放,拖动鼠标,让虚线框框住一个或多个组件,放开鼠标按键就完成选择,但是一些组件是添加在其它组件中间的,鼠标拖拽会带动组件移动,可以按住Ctrl键完成框选工作来避免。
  当我们需要选择一个组件,然而这个组件恰好被其它组件完全覆盖时,可以在对象观察窗口中选择它,或者选择到这个组件中包含的子组件,然后按下Esc键。同样再次按下Esc键会选择到这个组件的父组件,最终会选择到包含这些组件的窗口。
  3.使用对象观察窗口
  对象观察窗口会显示当前选中组件的属性和事件,如果选中的是多个组件,则显示这些组件相同的属性和事件。
  现在我们学会了把组件放上窗口,在让它们为我们工作以前,我们得先学会一种能管理和指挥它们的语言C/C++。Borland C++ Builder(BCB)是工具,而C/C++才是语言。
  三、什么是C/C++?
  C语言是使用非常广泛的编程语言,C++是在C语言的基础上发展而来的,可以说C++是C的超集。C++兼容C的很多语法,但是也有C没有的限制,不过C编写的代码可以在C++中进行少量修改或者无需修改就可以正常运行。
  1.编写C/C++代码
  void __fastcall TForm1::FormCreate(Tobject *Sender)
  {
    Form1->Caption = "Hello World!";
  }
  这条简单的语句意思是在创建窗口时将窗口(Form1)的标题(Caption)设定为"Hello World!"。其中
  void __fastcall TForm1::FormCreate(Tobject *Sender)
    {
    }
  是由编辑器自动生成的。在设计窗口的空白处双击鼠标,代码窗口中就会定位在窗口的创建函数中。在对象观察窗口的Events(事件)页面,双击某个事件,编辑器也会自动生成该事件的处理函数。关于具体组件的属性和事件将在VCL组件的应用中详细说明,这里我们重点关注C/C++的语法特点。
  C/C++代码的书写给程序员很大的灵活性,代码并不需要写在同一行上,每个语句总是以分号结束。上面的语句可以写成:
  Form1->Caption =
  "Hello World!";
  2.变量、赋值
  变量可以储存一定的数据,变量名由英文字母、数字和下划线组成,必须以英文字母或者下划线开头,一般编译器将下划线开头的变量作为特殊变量或者函数的开始。特别注意的是C/C++是区分大小写的,XYZ和xyz是两个不同的变量。
  变量声明由变量类型、变量名称组成:int a;  //声明变量a为整型变量
  双斜杆(//)是行注释符,它后面到行结束都是注释。C/C++也支持多行注释/*(注释开始)和?*/(注释结束)
  声明过的变量如果不赋一个初值,那么变量的值将是不确定的,这和VB等语言不同,必须养成在使用变量或者其它对象前进行初始化。C/C++允许变量在声明的时候赋一个初始值:int a = 100; 声明整型变量a,值为100
  也可以同时声明几个变量:int a, b = 10, c = 2; 声明了a,b,c三个变量,b,c有初始值。
  3.变量的作用域
  变量的作用域决定了变量的使用范围,分为局部变量(Local)、全局变量(global)、静态变量(static)和外部变量(external)。
  局部变量的作用域只是在一个函数的内部,变量值的改变不会影响函数外同名变量。
  Void __fastcall TForm1::FormCreate(Tobject *Sender)
      {
      int x, y;  //声明局部变量x, y
      x = 10;
      y = 25;
      ShowMessage((String)(x * y));  //显示x, y相乘的结果
      }
  x, y就是局部变量,只能在函数中使用,函数结束它们就被释放了。
  C/C++的初学者可能会对ShowMessage((String)(x * y))有疑惑。ShowMessage是Windows的API函数,作用是显示一个消息窗口,消息内容是这个函数的参数,参数是字符串型变量,(x * y)是整数型,不能直接赋值,因此需要使用强制转换语句(String)转化。
  静态变量与局部变量不同的是,变量只在第一次调用函数时赋初值,函数完成时保持变量值不变。
    Void teststatic()
  {
    statics int Count = 0;  //声明一个静态变量,赋初值为0
    Count = Count + 1;  //每调用一次函数Count加1
    ShowMessage((String)Count);  //显示函数调用次数
  }
  同时Count又是teststatic函数的私有变量,因此不会被其它函数改变。
  全局变量在整个单元中可以被本单元的所有函数访问和修改,全局变量需要在函数体外声明,或者在单元的头文件中声明(.h),在一个新工程的窗口代码中可以看到有一个:
  TForm1 *Form1;
  Form1是一个全局变量,也是一个指针类型的变量。
  外部变量将局部变量的作用范围扩大到整个应用程序,需要通过extern关键字声明。在代码编辑窗口中点击鼠标右键,在弹出菜单中选择 Open Source/Header File, 打开单元头文件就能看到 extern PACKAGE TForm1 *Form1; 将变量Form1声明为一个外部变量,让整个工程的单元都能够访问它。
  4.变量类型
  C/C++支持一系列基本的数据类型,这些类型是由语言本身定义的,其它的任何数据类型都建立在这些基本类型的基础上。(

)
  
  signed和unsigned是变量有无符号的修饰词,除了char类型外其它类型都是默认有符号(signed)。浮点类型变量受到计算机处理的精度限制,无法处理非常接近0的数字,只要对精度要求不是很高,我们都认为浮点类型是准确的。、
  5.运算符
  C/C++支持大量的运算符,功能强大,相对其它语言显得很复杂。对于初学者主要建立对这些运算符的印象,并不需要立即把它们都弄明白。
  (

)
  四、最常用的控制结构
  控制结构可以用清晰的方式描述判断和循环。这里介绍最常用的if、while、for、do、switch。
  1.If语句
  语法:if(表达式)语句 [else 语句]
   if(表达式){执行代码} [else {执行代码}]
  方括号中的部分是可以省略的。
  例子:
  if(a == 0)ShowMessage("a 等于 0");
  if(a == 0)ShowMessage("a 等于 0"); else ShowMessage("a 不等于 0");
  
  if(a == 0){
   …
  } else {
   …
  }  
  大括号{}中间可以由多条语句组成,if语句也可以嵌套使用,如:
  if(表达式){执行代码} else if(表达式){执行代码}
  
  2.while语句
  循环控制语句,原型:
  while(表达式)语句
  while(表达式){执行代码}
  如:
  while(count < 10){  //做十次循环
  …
  count++;
  }
  
  3.Do语句
  循环控制语句,原型:
  do 语句 while(表达式)
  do {执行代码} while(表达式)
  与while不同,do语句判断是否继续循环的控制条件是放在做完一次循环以后,就是说无论怎样,do都要完成第一次循环。当表达式值为假时就停止循环。
  4.For语句
  for循环是一个确定,不像while用一个表达式来控制循环,它的原型:
  for([初始化条件] ; [循环结束条件] ; [增量])执行代码
  
  for(int a = 0; a < 10; a++){…}  //做十次循环
  原形中方括号部分可以省略,上面的程序也可以写为:
  int a = 0;
  for(;a++ < 10;a++){…}
    
  5.Switch语句
  条件选择语句,根据控制表达式的值选择执行相应的代码,原型:
  switch(表达式)
  {
  case 值1 :
  执行代码
  [break;]
  case 值2 :
  执行代码
  [break;]
      …
  [default :
      默认执行代码]
  }
  switch先计算表达式的值,然后执行对应的case部分。如果没有对应的case部分就转到default部分,用break表示结束,否则将执行到下面的分枝。Switch只能对整数操作,不支持对字符串和对象的操作。
  
  Char c;
  …
  switch(c)
  {
  case 'a' :
  case 'b' :
  case 'c' :
  ShowMessage("有效值");
    break;
  case 'd' :
  ShowMessage("无效值");
    break;
  default : ShowMessage("不确定值");
  }
  只要c等于'a', 'b'或者'c'都显示有效值。
  
  五、指针
  指针使得C/C++语言变得强大,也让人难以理解,是众多朋友学习C/C++一大障碍。
  我们应该怎么理解指针?
  简单来说指针就是存贮内存地址的变量。
  (

)
  看起来指针像个整型变量,它的特殊意义在于告诉处理器在内存的哪个位置可以找到数据。*p就可以访问p指针指向的值,如上面例子中的128。
  【指针和实例】
    int a = 128, b;
    b = a;
  a, b是int型变量,a对b赋值是数据拷贝,修改一个变量的值不会影响另一个变量。
    Int a = 128;
    int *p = &a;  
  由于*p和a是指向同一个内存地址的值,所以
    a = 32; 或 *p = 32;
  它们是等价的。
  实际上我们很少用int类型的指针,因为这样意义并不大(除非作为函数可变参数,下一节函数将介绍),只是作为例子帮助大家理解指针。指针在大多数时候用作大量数据的传送。
  使用指针必须先为指针分配内存,且在使用完以后需要释放分配的内存:
  String *vStr;
  vStr = new String;  //为vStr分配内存空间
  *vStr = "Hello World!";
  String S = *vStr;  //赋值给字符串实例S
  delete vStr;  //释放指针
  
  对于例子中的实例S,访问它的成员要使用直接访问符号(.)
  S.Length()  //计算字符串的长度
  而指针vStr访问成员就必须使用间接访问符号(->)
  vStr->Length()
  
  【指针与数组】
    int a[100];  //声明包含100个整型变量的数组
    int I = 0;
    while(I < 100)a[I++] = 25;  //将数组中的每个元素初始化为25
  
    如果用指针来做:
    int a[100]
    int I = 0;
    int *p = a;  //将数组a的开始地址传给指针
    while(I < 100)*p++ = 25;
    p首先指向a[0],*p赋值为25,指针下移指向a[1]
  
  六、函数
  在使用函数前必须对函数进行声明,还需要写函数的具体代码。声明函数的原型:
  函数返回类型 函数名([参数]);
  例如:int add(int a, b);
  函数的实现代码:
    int add(int a, int b)  //必须和声明的函数原形一致
  {
   return a + b;  //返回a + b的值
  }
  以后我们就可以对函数add进行调用:add(3, 5);
  如果函数不返回任何值,那么它的类型为void
  void doSomething(int param);  
  函数不需要return语句返回值,但是可以用return;提前退出函数。
  Void doSomething(int &param)
  int a = 100;
  void doSomething1(int &param)
  void doSomething2(int param)
  void doSomething1(int &param)
  {
    *param = 25;
  }
  void doSomething2(int param)
  {
    param = 25;
  }
  doSomething2(a);
  ShowMessage((String)a);  //a等于100,值没有被改变;
  doSomething1(a);
  ShowMessage((String)a);  //a等于25;
  
  【函数的重载】
  函数名称相同,有两种或几种不同的参数或返回值,编译器根据调用函数时的参数,选择对应的函数执行。下面的例子是一个类似条件运算符(?:)的函数。
  Int iif(bool express, int truevalue, int falsevalue);
  String iif(bool express, String truevalue, String falsevalue);
  
  int iif(bool express, int truevalue, int falsevalue)
  {
   if(express)return truevalue; else return falsevalue;
  }
  String iif(bool express, String truevalue, String falsevalue)
  {
   if(express)return truevalue; else return falsevalue;
  }
    int a;
    ……
    ShowMessage(iif(a > 2, "a大于2", "a小于等于2"));
    int c = iif(a > 2, a * 10, a);
  
  【怎样声明、使用函数指针】
  一般函数的指针是在调用动态连接库里的函数和回调函数时使用。声明函数指针和声明变量指针有很大差别:
  void(*p)();  //声明一个没有参数,无返回值的函数指针p
  可以将函数 void doSometing(); 的地址赋给p
  p = &doSomething;
  p();  //调用doSomething
  我们可以用更灵活的方式来使用指针:
  int __fastcall doSomething(int param);  //doSomething函数的原形
  Pointer p = &doSomething;  //声明p为一个指针指向doSomething的地址
  由于Pointer是没有规定类型的指针,所以在使用p调用doSomgthing函数时要先结果类型转换。
  ((int(__fastcall *)(int param))p)(5);
  
  七、枚举、结构、类
  【枚举变量】
  枚举是一系列的条目。每个条目由编译器或者程序员分配一个识别数字,在编程的时候需要定义一系列常量(const),且保证这些常量各不相同,那么使用枚举将是非常有效率的。枚举的语法格式:
  enum [枚举名称] {
    项目名称, 项目名称, ……
  } [枚举变量名称];
  方括号([])中的内容是可以省略的
  
  enum TMyColor {Red, White, Yellow}MyColor;
  MyColor = Red;
  
  enum TMyNum {twelve = 12, thirteen, twenty = 20, twenty_one};  //注意:省略了枚举变量名但是不能省略最后的分号
  twelve指定值为12,那么thirteen就是它前面一个值加1即13
  TMyNum MyNum;  //声明MyNum是枚举变量
  MyNum = twelve; 或者可以写成 MyNum = (TMyNum)12;
  
  【结构】
  结构由struct或者union关键字声明,结构包含各种成员,是公有访问类型数据成员的集合。它的语法格式如下:
  struct 名称 [: 基类] {
    数据类型的声明
  }[变量名];
  
  enum Tsex {male , female};
  struct Temployee {
    String name;
    Tsex sex;
    int age;
  };
  定义一个包含雇员的姓名、性别和年龄的结构:
    Temployee employee;  //声明变量
    emploree.name = "小丽";
    employee.sex = female;
    employee.age = 21;
  
    结构是具有继承性的,它可以继承基类中的成员:
    struct Tperson : Temployee  //从Temployee继承
    {
      String work;
      float income;
    };
    Tperson person;
    person.name = "小丽";  //从Temployee继承过来的成员
    person.work = "秘书";  //Tperson自身的成员
    ……
  
  union和struct在语法上是一致的,不同的是union内部的所有成员都使用相同的内存地址和共同的内存空间,在你需要不同的时候保存不同类型的变量时这将非常有用。
    Enum {Int, Float, Char};
    struct Tcommondata {
      int data_type;
      union {
        int intdata;
        float floatdata;
        char chardata;
      };
    }commondata;
    
    commondata.data_type = Int;  //表明存放的是整型变量
    commondata.intdata = 10;
    commondata.data_type = Char;  //表明存放的是字符变量
    commondata.chardata = 'A';
    
    struct和union可以包含多个struct或union结构:
    enum {Int, Float, Char};
    struct Tcommondata {
      int data_type;
      union {
        int intdata;
        float floatdata;
        char chardata;
      };
      struct {
        Pointer p;
      } datapoint;
    }commondata;
    ……
    commondata.data_type = Int;  //表明存放的是整型变量
    commondata.intdata = 10;
    commondata.datapoint.p = NULL;  //赋一个空指针