VC++中的面向对象程序设计概念

本文深入探讨了VC++中如何使用C++进行面向对象程序设计,涵盖了类(class)的创建与使用,图形(graph)处理,以及内存管理的关键操作如delete。通过实例解析,阐述了面向对象特性在实际开发中的应用。
摘要由CSDN通过智能技术生成
面向对象程序设计概念
VC++应用程序是采用C++语言编写的。C++是在C语言的基础上进行改进与扩充,是既面向对象又面向过程的一种混合程序设计语言。
传统的程序设计思维方式是基于“算法+数据结构=程序”的模式,在这类程序中,数据和施加于数据的操作(算法过程)总是分离的,所有程序均有一组被动的数据和一组能动的过程所组成。通常把这类程序设计称为面向过程的程序设计,把支持这类程序设计的语言称为面向过程的语言(procedure-oriented language ,简称POL)。C语言就是其中的一种。C++保留了C语言的基本语法和流程,C程序几乎都可以在C++环境中不作修改被运行。
面向对象程序设计(object-oriented programming,简称OOP)将数据及对数据的操作放在一起,作为一相互依存、不可分割的整体来处理,它采用数据抽象和信息隐藏技术。它将对象及对象的操作抽象成一种新的数据类型——类,并且考虑不同对象之间的联系和对象类的重用性。概括为“对象+消息=面向对象的程序”。
本章将在C语言基础上对比介绍C++的基本语法,并扩充到面向对象程序设计的基本概念,使读者能够对在VC++应用程序开发中遇到的语法现象有个初步的理解。
2.1 C++与C的基本语法区别
2.1.1 一般语法区别
1. 注释
C++支持的注释方法有两种:
(1)     /*……*/
(2)     //……
“/*……*/”是C语言中所使用的注释方法,在C++中继续延用,一般在连续多行注释时使用。“//……”只能单行注释,进行注释的内容从“//”后的第一个字符直到本行结束。在使用AppWizard生成的MFC应用框架中会默认自动插入大量注释如程序清单2-1所示,“// TODO……”注释行提醒程序员添加代码的位置和通常所作的操作。
 
程序清单2-1: 加注释的C++程序
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
           return FALSE;
    // TODO: Modify the Window class or styles here by modifying
    // the CREATESTRUCT cs
 
    return TRUE;
}
 
注释一行不要太长,一般60个字符以内(保证在VC++集成编辑环境的可见区域之内),如有超过,建议换行处理。
 
 
2. 常量的定义
在C语言中,符号常量的定义是通过宏定义#define来实现的,其实质是字符串替换。例如下面语句定义了一个符号常量PI:
#define PI 3.1415926    
在C++中保留#define定义符号常量的方法,但更多地主张采用关键字const来定义符号常量。例如PI的定义可以用下面语句表示:
const float PI=3.1415926;
注意:用关键字const定义的符号常量必须指定其数据类型,而用宏定义的符号常量是没有数据类型的;用关键字const定义的符号常量在编译时为其分配相应的内存空间。规定了符号常量的数据类型,便于编译系统检查参数的数据类型,C++的编译系统检查比C更为严格。
 
3. 变量的定义
在c语言的函数体中,定义部分和执行语句部分是相对分离的,对局部变量的定义必须出现在函数体或分程序内所有执行语句之前。C++的函数体不再区分定义部分和执行部分,用户可在函数体的任意位置定义一个局部变量。因此一个变量尤其是中间变量,在需要时再定义,这样便于阅读与维护。例如可以在for语句中定义循环变量:
int c=1;
for(int i=0;i<10 ;i++)
{ c*=2;
 ……
}
 
在C++程序中,要注意区分各种变量的作用范围和生命周期,变量的类型有:
(1)     局部变量(local variable)
在一个函数体内定义的变量,只在本函数范围内有效,在本函数外不能使用。
(2)     形参变量(formal parameter)
向函数传送的变量,同时又能象其他局部变量一样使用。
(3)     全局变量(global variable)
在函数体外定义的变量,其有效范围为:从变量定义处开始直到本源文件结束。
(4)     成员变量(member variable):
在一个类中定义的变量,对类中的所有成员函数都是有效的。在一个继承体系中,根据访问类型和继承类型的不同,对派生类的作用范围会有不同,参见后面章节对继承的讨论。
 
4. 强制类型转换
C++保留了C语言的显式强制类型转换法:
(类型名)表达式
同时还提供了函数表示法:
类型名(表达式)
例如:
int i=int(1.35); //给i赋一个初始值
函数表示法的函数名只能使用简单类型名称,即int、float、double、char。
 
5. 动态变量创建
C语言中用函数malloc()动态分配存储空间,用函数dispose()动态释放已分配的存储空间。C++中提供了两个类似该函数的运算符new和delete,它们能完成malloc()和dispose()的功能,而且更为方便和优越。
(1)     new 运算符
使用new 运算符向内存的“堆”申请某个大小的存储空间,返回存储空间的首地址。空间大小由数据类型决定,分配失败返回空指针。使用new的语句格式如下:
指针 =new数据类型(初始化值)
指针 =new数据类型[算术表达式]     //分配拥有多个连续空间的动态数组
例如:
int *pi ,*parray;
pi=new int(85);     //分配一个int型的内存单元,赋初值为85,首地址赋给int型指针pi
parray=new int[10];     //分配10个int型(数组)的内存单元,首地址赋给int型指针parray
(2)     delete运算符
delete运算符用来释放通过new运算符得到的内存空间。使用delete的语句格式如下:
delete 指针
delete [] 指针    //释放整个数组占用的空间
例如:
delete pi;      //释放p指向的内存单元
delete [] parray;  //释放parray指向的动态数组内存块,方括号内不要写元素个数
 
6. 输入输出语句
在C++中继续支持使用C的外部库函数(如printf和scanf等)进行输入输出,以兼容C程序的执行。C++本身引入了流的概念来处理数据的输入输出。
所谓的流就是指数据之间的传输操作,包括输入流和输出流。输入流表示数据从载体(如数据文件)或设备(如键盘)流向内存的数据结构,输出流表示数据从内存的数据结构流向载体或设备(如显示器)。流的操作由C++的标准库iostream.h提供,也就是说,如果要使用流操作必须包含库文件“iostream.h”。
输入输出流操作包含两个流对象:输出设备cout和输入设备cin;两个操作符:插入操作符“<<”和抽取操作符“>>”。进行输出时的语句格式为:
cout<<输出内容[<<输出内容...];
例如:cout<<”a=”<<a<<endl;    //endl表示换行,等价于“/n”
进行输入时的语句格式为:
cin>>变量1[>>变量2...];
例如:cin>>x>>y;
程序清单2-2演示了两种不同的输入输出方法的使用:
 
程序清单2-2:C与C++的输入输出比较
(1)#include “stdio.h”                         (2)#include “iostream.h”
   void main()                                void main()
   {   int a,b,sum;                            {   int a,b,sum;
       printf(“input a b:”);                          cout<<“input a b:”;
scanf(“%d%d” ,&a,&b);                       cin>>a>>b;
sum=a+b;                                   sum=a+b;
printf(“sum is %d/n”,sum);                       cout<<”sum is ”<<sum<<endl;
   }                                         }
 
 
cout和cin的优点是可以自动调整输出和输入格式,而不必象printf和scanf都要由使用者一个个指定;另外cout和cin支持用户自定义的数据类型(printf和scanf不支持)。
2.1.2指针和引用
引用是 C ++的一个特征,可以把它看作是一个常量指针,并自动被编译器逆向引用。指针是指对象(变量)的地址,而 引用是指给对象的地址取一个别名。引用通常应用于函数参数表中作为参数实现双向传值,但也可以作为一个引用变量使用。
 
1. 引用变量
引用变量的说明方式是:
<类型> &引用名=变量名或对象名;
例如:
int a;
int &b=a;     //合法定义引用类型
int &c;       //错!非法定义引用类型
b++;
这里b是a合法的引用变量,b是a的别名,不再为b分配空间,a,b共用同一存储单元,对b的操作与对a的操作效果相同,执行b++等同于执行a++。
引用变量定义时必须初始化,对此可以这样理解,指针变量的指向可以改变,但作为常量指针的引用,它的指向是不能改变的,所以在创建一个引用时,它必须指向一个特定的合法的存储空间,并且在程序运行过程中不能改变。
 
2. 引用参数
最常看到引用的场合是在函数的参数表中。C与C++函数参数传送是采用单向传值,形参得到实参的拷贝值。如果需要逆向传值时,即将修改过的参数值反向传递回函数调用处,必须采用传地址的方法,即使用指针变量,直接操作内存空间。而在C++中更好的方法是使用引用参数,即把形参定义为引用变量,编译器会自动地实现逆向传值,引用具有更清晰的语法。
 
程序清单2-3:引用参数举例
#include "iostream.h"
void AutoInc1(int*x);
void AutoInc2(int &y);
void main()
{int a(10);
 AutoInc1(&a);
 cout<<"a="<<a<<endl;
 AutoInc2(a);
 cout<<"a="<<a<<endl;
}
void AutoInc1(int*x)
{ (*x)++;
}
void AutoInc2(int &y)
{y++;
}
运行结果:
a=11
a=12
 
在上面的示例中,定义两个函数AutoInc1和AutoInc2的作用都是增1操作。AutoInc1形参采用的是指针,调用时需传递地址,而AutoInc2形参采用的是引用。可以看到AutoInc2的实现代码更为简单,调用时隐藏性好,即调用代码不能确定是传值还是传地址。
2.1.3函数的改进
1. 函数原型
C++中的函数原型其实就是C语言中的函数声明的概念,用于告诉编译系统使用函数的信息,包括函数的返回类型、参数个数和参数类型。
函数原型通常放在程序的开始部分或者包含在头文件中,确保编译器在该函数被调用以前就已经“认识”该函数,其语法形式为:
返回类型   函数名(参数表);
例如:
char* substring (char* str, int start ,int count);
也可写成:
char* substring(char*,int, int);
C的类型检查的机制较为薄弱,在很多情况下函数声明都可以省略,但在类型检查更为严格的C++中,所有函数皆必须声明后才可使用,这便是C++所特别要求的函数原型。编译系统对下面情况会给出错误信息:
(1)     实参和形参的类型不匹配,且实参向形参自动类型转换非法。
(2)     实参与形参的个数不一致。
(3)     函数没有按函数的类型返回数据。
例如:在C++中main函数前必须指明返回类型为void,否则会出现编译错误,main()函数的一般定义如下:
void main()
{}
 
2. 函数重载
函数重载是指同一个函数名可以对应着多个函数的实现。函数重载允许一个程序内声明多个名称相同的函数,这些函数通常执行相同的功能,但是带有不同类型、不同数目的参数或不同类型的返回值。例如,要写一个求两个整数之和与两个浮点型数之和的函数如下:
int plus (int x, int y){return x+y; }    //整数求和函数
double plus(double x, double y){return x+y; } //浮点数求和函数
以上实现的是两个不同参数类型的重载。这样在调用时可用同一个函数名plus调用,程序会自动完成正确的调用。如:
int z=plus(2,3); //调用整数求和函数plus
double z= plus(2.0,3.5); //调用浮点数求和函数plus
编译系统解读函数原型,识别重载。为了使编译系统能确定采用哪一个函数的实现,要求重载函数的参数个数和参数类型必须有所不同,否则产生二义性错误。
 
3. 设置默认参数
调用函数时,若所用的参数有一个经常用的值,在声明函数原型时,可以用该值作为函数参数的默认值。凡有默认值的参数,在函数调用时如果提供实参,形参则接受实参传递的数值,如果没有给出实参,形参则接受默认值。例如,下面程序代码中的延时函数,第四次调用 delay()时没有给出实参,就按默认值1000延时,其它调用都给出了实参值,就按给定的数值延时。
 
程序清单2-4:函数参数默认值举例
#include “iostream.h”
 void delay(int t)
 {
   if(t==0)   return;
   for(int i=0; i<t;i++);
   cout<<”i=”<<i<<endl;
 }
void main()
{
 void delay(int=1000); //声明默认值参数
 delay(0);
 delay(50);
 delay (500);
 delay();
 delay(5000);
}
运行结果为:
    i=50
    i=500
 i=1000
i=5000
 
注意:
(1)   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值