c++ 总结之一

比较是学习的一个很有效的方法。c 被认为是最贴近机器语言和执行效率最高的语言,语法规则也不复杂。关于C的知识就懒得写了。

C++是在c的基础上扩展了很多。现在就比较一下:

1。C++有了类的概念,有了面向对象的概念。语言本身是人设计的,为了实现这些变化,操作系统本身是做了很多的改动的。开发语言离开操作系统就变得没有意义。

     正如大家知道,win32系统有大量的C++运行库,每个在Win32系统上跑的程序都会调用到这些C++运行库。所以C++这个语言个人认为对于在win32上的开发是非常重要的。退一步说,即便不在win32上作开发,C++这个语言的设计本身就足以提供大量的设计思想和模范。这些都是很宝贵的。

2。类的概念貌似非常容易,无非是一个带属性和操作的结构体,使用时,声明一个变量为该类,就可以了。但实际这里面有些问题必须彻底搞清楚,才可以写出让自己放心的程序。自己放心了,胆气就足了。因为C++在C之后开发出来的,C的很多毛病在C++上得到了一定的纠正。例如C程序员经常会犯的毛病,变量不做初始化就使用。

    C++为了这个毛病就设立了一个构造函数的东西出来。我认为从这个角度来理解一些东西,才更有体会,而不再是象个机器人一样拼命跟着流行跑,跑得气喘吁吁,却依然不会设计程序。

我决定换一个写作的角度,打破这种逐一介绍各个知识点的方法。从一个点出发,将与之关联的各个知识点串联起来,这或许更符合我们的思维方式。

现在就由面向对象开始吧!好了,我们开始面向对象了,试想会遇到什么问题?例如我定义了A类,并声明a1,a2是A的实例。当操作系统加载我的程序时,a1,a2的程序代码是一样的,也就是它们都在代码区,但是a1,a2有各自不同的数据,这些数据和代码是分开的,当执行代码时,我如何知道去取a1和a2的各自的变量呢?这就牵扯到了我们第一个知识点,this指针。this指针就是类的实例起始地址——实例的变量存储区的起始地址,和代码区是分开的。有了this指针我就可以访问我的实例的变量,并传递给代码区区执行。值得注意的是,this指针本身并不是实例的一部份,所以不会影响sizeof(实例)的大小。

看下面这个有意思的例子:

虽然编译器会给这两个函数传递this指针,但是它们并没有通过this指针来访问类的成员变量,因此call 2和call 3两行代码可以正确调用;而对于成员函数Test4()要访问类的成员变量,因此要使用this指针,这个时候发现this指针的值为NULL,就会造成程序的崩溃。   
你在调用一个类的成员函数时,编译器会把该实例的this指针当作参数传递给该函数,如果出现访问成员变量,就会根据该指针去寻址。如果不幸该指针为空——娃哈哈,程序崩溃。在VC6之上的开发环境中,你可以把一小部分代码编译成汇编语言,如果你这么做,你会发现,this指针跟一般的函数参数的区别:一般的函数参数是直接压入栈中(push 0Dh),而this指针却被放到了ecx寄存器中。
很显然,this指针的作用域只在类内部,不可能由它去找到其他的变量。

 

谈到类的数据,牵扯到另一个东西——静态成员变量。静态就是在程序编译时就分配存储空间,而不是等到运行时才知道,也就是程序加载之后,它的存储空间就已经分配了。为什么要做这种设计呢?因为我们有时候希望即便类的实例销毁了,但我却希望保存它的某些数据,那么这个时候,静态成员变量就是一个很好的选择。

 对于被所有类共享的数据可声明成静态变量,它在程序运行前就已经存在了(所以一定要初始化),它被放到哪里去了呢?静态存储区,按照出现次序被初始化。 它被所有该类的对象共享,静态变量可以被改变。

tips:

1。静态变量可以被继承,如果子类想屏蔽,也可以定义一个一样的静态变量。
2。初始化: int ClassName :: varname=90;  看到了,前面没有static。它不能在类体外进行。
(未完待续。。。)

 

字符串:

在标准C中,是没有字符串变量的,但是有字符数组。而且标准C带有的标准库函数:string.h中包含了大量的字符串操作函数,当然如果必要的话,你也可以自己写代码实现这些函数的功能。(对于字符串的操作,我的建议是你应该非常熟练的写出各种常用功能的函数)我曾经碰上个一个问题,让我放弃使用stirng.h 中的strcpy函数,而自己完成该功能。因为string.h中的各种功能都针对char[]型的,假设你对标准C非常熟悉,你应该知道,对于我的 unsigned char[]这些函数都无效,所以这迫使我必须自己处理它们。我后来查了资料,似乎有一组处理unsigned char[]的函数,但是当我使用它们的时候,依然无法满足我的要求。

我认为即便C语言再简单,即便这些知识看起来是多么枯燥和简单,依然有必要回顾并牢记它们:

对于32位操作系统

int (2字节)  short (1字节) long(4字节)

unsigned  char 从0到256之间
char   从-128到127之间
byte  字节就是无符号的字符
unicode:两字节的字符

由此可见:byte=nusigned char, short=char

 

 CString类, 是由微软公司集成在VC的MFC里面,包含字符串各种常见操作的类。其源码可以在MFC里面找到。
当声明一个字符串变量,首先会调用构造函数,在成功后,便可利用它的常见操作。

当我们在利用CString 类便捷性时,有些特殊化的东西无法做,于是相互之间的转换变经常被需要:
在转换之前必须确保你的字符的范围在你的范围之内。
1.CStirng转 char *
传给未分配内存的指针.
  CString cstr1="ABCD";
  char * ch=cstr1.GetBuffer(cstr1.GetLength()+1);  //获取指向CString最后一个字符的地址。
  cstr1.ReleaseBuffer();
注意:用完ch后,不用delete ch,因为这样会破坏cstr内部空间,容易造成程序崩溃.

值赋给已分配内存的char *
    CString cstr1 = "ASDDSD";
    int strLength = cstr1.GetLength() + 1;
    char *pValue = new char[strLength];
    strncpy(pValue, cstr1, strLength);

赋值:
char* psz = “joise”; 没有构造函数,仅可以赋值(因为它本身就是基本型)

CString cstr( psz ); 可以从基本的一些字符串变量构造而来,包括char*等

string str( cstr );  可以从几乎所有的字符串构造而来,包括CString和char*;

以上也可以看作由 char *转CStirng的办法。

 

1.char *:
char *psz = NULL;
psz = new char[10]; //当然,以上的直接写成char *psz = new char[10];也是一样
memset( psz, 0, 10 );
strcpy( psz, “joise” );
2.CString:
CString cstr;
cstr = psz;  字符指针直接赋值
3.string:
string str;
str = psz;   字符指针直接赋值
str = cstr;  CString变量直接赋值
delete []psz;

string与CString差不多,可以直接与char*进行加法,但不可以相互使用+运算符
char*没有+运算,只能使用strcat把两个指针连在一起;
strcat( psz, cstr );//合法
strcat( psz, str );//非法,由此可见,CString可自动转换为const char*,而string不行

posted on 2010-03-21 22:43  袁婉轩  阅读(137)  评论(0编辑  收藏  举报

导航