用const声明的变量被称为常变量,常变量在程序运行期间是不能改变的
const int a = 3; //其指定值始终为3
在定义常变量时必须同事对它初始化(既指定其值)。此后它的值不能再改变
string在C++中也有定义。在使用方法上和其他int,char类型一样。可用来定义变量,字符串常量以“/0”作为结束符。但将字符串常量存放到字符串变量中时,只存放字符串本身而不存放“/0”。并且在字符串中:
1。字符串赋值用赋值号
2。字符串连接用加号
3。字符串比较直接用关系运算符
为动态的分配和撤销内存,C++中使用了new和delete这两个运算符。注意:new和delete是运算符,不是函数,因此执行效率高。
new运算符的例子
new int;//开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(指针)
new int(100); //开辟一个存放整数的空间,并指定该整数的初值为100,返回一个指向该存储空间的地址。
new char【10】;//开辟一个存放数组(包括10个元素)的空间,返回首元素的地址。
new int【5】【4】;//开辟一个存放二位数组的空间(5*4),返回首元素的地址。
float *p = new float(3.14159); //开辟一个存放单精度浮点数的空间,并指定该实数的初始值为3.14159。将返回的该空间的地址赋给指针变量p。
typedef可用来声明一个新的类型名来代替已有的类型名。习惯上常把用typedef声明的类型名用大写字母表示,以便于系统提供的标准类型标示符相区别。
类和对象
1。在声明类的类型时,不占用内存空间
2。如果声明了类,定义多个类的对象,对于static变量来说,每一个对象的static变量都相同。若一个改变,则全部static变量都改变。共享同一个static变量。
3。static变量属于整个类的,也称为类变量。
4。在定义一个对象时,编译系统会为这个对象分配存储空间,以存放对象中的成员。
5。如果没有数据部分,只有操作,则对象占用空间至少为1。根据不同的编译器不同。
类的成员函数
类的成员函数可在类的外部进行定义。在外部进行定义时,需要用到“::”(作用域限定符)。用来声明函数是属于哪个类的。如果作用域运算符的前面没有类名,或者函数前面既无类名又无作用域运算符。则表示该函数不属于任何类。这个函数不是成员函数,即为一般的普通函数。
类函数必须在类体中做原型声明。然后在类外定义。也就是说类体的位置应该在函数定义之前,否则编译时出错。
inline成员函数
1。如果在类体中定义的成员函数中不包括循环等控制结构,C++系统会自动将它们作为内置(inline)函数来处理。
2。在类内定义的成员函数,可以省略inline,因为这些函数已经被隐性的指定为内置的函数。
3。应该注意的是:如果成员函数没在类体内定义,而在类外定义,则系统并不把它默认为内置函数。调用这些函数的过程和调用一般函数的过程是相同的。如果在类体外定义内置函数,则需要加关键字inline,并将类定义和成员函数的定义都放在同一个头文件中(或者写在同一个源文件中)
成员函数的存储方式
每个对象所占用的存储空间只是该对象的数据部分所占用的存储空间,而不包括函数代码所占用的存储空间
类的作用是把数据和算法封装在用户声明的抽象数据类型中
在声明时一般都是把所有的数据指定为私有,使它们与外界隔离,把一些成员函数指定为公有的,外界通过公共的函数来实现对数据的操作。
当要被#include包含的文件在用户当前目录中时,该被包含的文件名要用“”括起来,而不用尖括号<>,否则,编译时会找不到该文件。
构造函数
构造函数有一种形式是在类中声明时对函数中的各值进行初始化
1。在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。
2。如果构造函数的全部参数都指定了默认值,则在定义对象时可以给出一个或者几个实参,也可以不给出实参。
3。如果一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数,但如果构造函数的参数并非全部为默认值时。有可能可以,有可能不行,看情况而定。
当有自己写的构造函数时,系统默认的构造函数会消失。
析构函数
析构函数不返回任何的值。没有函数类型也没有函数参数。由于没有函数参数,因此它不能被重载,一个类可以有多个构造函数但只能有一个析构函数。
在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,起对应的析构函数最先被调用。以上所说的是对同一类存储类别的对象而言。
对象指针
对象空间的起始地址就是对象的指针。对象指针访问自己的数据成员和函数成员的方法等同于struct
定义指向对象成员函数的指针变量的方法和定义指向普通函数的指针变量方法有所不同。定义指向对象成员函数的指针变量表示方法为:
void (Time :: *p)(); //定义p为指向Time类中公用成员函数的指针变量。
注意(Time :: *p)两侧的括号不能省略。
定义指向公用成员函数的指针变量的一般形式为:
数据类型名 (类名::*指针变量名)(参数列表)
指针变量名 = &类名::成员函数名;
这一定是类名而不是对象名,和数据不同。函数在多个对象中使用的是同一份拷贝。
this指针
在每一个成员函数中都包括一个特殊的指针。这个指针的名字是固定的,称为this。当调用成员函数a.volume时,编译系统就把对象a的起始地址赋给this指针,于是在成员函数引用数据成员时,就按照this的指向找到对象a的数据成员。
常对象
常对象中的数据成员为常变量且必须要有初值。
常对象中的所有数据成员的值都不能被修改。
定义常对象的一般形式为:
类名 const 对象名[(实参表列)]
const 类名 对象名[(实参表列)]
如果一个对象被声明为常对象,则不能调用该对象的非const型的成员函数,若要访问某成员函数时,则需要将该成员函数声明为const。
而如果说常对象中的某一值一定会修改,例如如果有一用于计数的int型const变量,则可将该变量声明为mutable类型。
1。常数据成员
const int hour;//声明hour为常数据成员,只能通过构造函数的参数初始化表为常数据成员经行初始化。
在类体中声明了某一个常数据成员为常数据成员后,该类所有对象中的该数据成员的值都是不能改变的。但不同对象中该数据成员的值可以是不同的(在定义对象时给定)
2。常成员函数
void get_time() const;//在后面
如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们。在这里,const成为函数类型的一部分,在声明函数和定义函数时都要用到const关键字。
常成员函数可以引用const数据成员。也可以引用非const的数据成员,而对立的,const数据成员可以被const成员函数引用,也可以被非const的成员函数引用。
不要误认为常对象中的成员函数都是常成员函数,常对象只保证其所有数据成员的值不被修改。如果在常对象中的成员函数未加const声明,编译系统就把它作为非const成员函数处理。
常成员函数不能调用另一个非const成员函数。
指向对象的常指针
指向对象的指针变量声明为const型,并使之初始化,这样指针指始终保持为其初值,不能改变,即其指向始终不变。
类名 * const 指针变量名 = 对象地址
但是可以改变其指向对象中数据成员的值。
指向常对象的指针
const 类型名 *指针变量名
1。如果一个变量已被声明为常变量,只能用指向常变量的指针变量指向它,而不能用一般的指针变量去指向它。
2。指向常变量的指针变量可以指向一个非const变量。这时可以通过指针变量访问该变量,但不能改变该变量的值。
3。如果函数的形参是指向非const型变量的指针,实参只能用指向非const变量的指针,而不能用指向const变量的指针。如果函数的形参是指向const型变量的指针,在执行函数过程中显然不能改变指针变量所指向的变量的值,因此允许实参是指向const变量的指针,或指向非const变量的指针。
而指向常对象指针变量的概念和指向常变量指针的概念是相同的。
当希望在调用函数时对象的值不能被改变,就应该把形参定义为指向常对象的指针变量,同时用对象的地址做实参(对象可以使const或非const)如果要求该对象不仅在调用函数过程中不被改变,而且要求它在程序执行过程中都不改变,则应把它定义为const型。
如果定义了一个指向常对象的指针变量,是不能通过它改变所指向的对象的值的。但是变量本身的值时可以改变的。
对象的常引用
一个变量的引用就是变量的别名,实质上,变量名和引用名都指向同一段内存单元。
对象的复制
在C++中,对象的复制是通过编写一个复制构造函数来实现的
如 Box :: Box (const Box &b)
{
height = b.height;
width = b.width;
length = b.length;
}
当Box box2(box1)语句执行时,就调用该复制构造函数。
如果用户自己未定义复制构造函数,则编译系统会自动提供一个默认的复制构造函数,其作用是简单地复制类中每一个数据成员。
还有一种复制方式是“=”号,其一般形式为:
类名 对象名1 = 对象名2;
这种方法叫做对象的赋值。
对象的复制和对象的赋值虽然达到的效果相同。但是其在概念上和语法上是不同的。对象的赋值是对一个已经存在的对象赋值,因此必须先定义被赋值的对象,才能进行赋值。而对象的复制则是从无到有的建立一个新对象,并使它与一个已有的对象完全相同(包括对象的结构和成员的值)
静态数据成员
静态数据成员,它就为各对象所共有,而不只属于某一个对象的成员,所有对象都可以引用它。
静态数据成员不属于某一个对象,在为对象所分配的空间中不包括静态数据成员所占的空间。静态数据成员是在所有对象之外单独开辟空间。只要在类中定义了静态数据成员,即使不定义对象,也为静态数据成员分配空间,它可以被引用。
静态数据成员可以初始化,但只能在类体外进行初始化。
数据类型 类名 ::静态数据成员名 = 初值
如果未对静态数据成员赋值,则编译系统会自动赋予初值0。
可以通过对象名引用公用的静态数据成员,也可以通过类名引用静态数据成员。这是由于静态数据成员不是专属于某个对象的。而是专属于某个类的。
静态成员函数
也可以用static修饰成员函数。静态成员函数是类的一部分而不是对象的一部分。如果要在类外调用公用的静态成员函数,要用到类名和域运算符“::”如
Box ::volume();
也可以通过对象名调用成员函数(可以通过对象访问静态成员函数)。
静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员
因为静态成员函数不属于某一个对象,所以在静态成员函数中没有this指针,既然它没有指向某一个对象,就无法对一个对象中的非静态成员经行默认访问(既在引用数据成员时不指定对象名)。
在C++程序中,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。