一、局部变量和全局变量
程序中的不同变量的不同范围称为作用域(Scope)。作用域就是变量的有效范围,作用域包含文件作用域、函数作用域、块作用域和函数原型作用域。其中,文件作用域是全局的,其他三者是局部的。
程序中的变量在内存中的分布被分成4部分。
(1)代码区:存放程序的代码,即程序中的各个函数代码块。
(2)全局数据区:存放程序的全局数据和静态数据。
(3)堆区:存放程序的动态数据。
(4)栈区:存放程序的局部数据,即各个函数中的数据。
二、面向对象编程的主要特点:
抽象、封装、继承、多态
类体现了封装和多态的特点。
三、构造函数
\qquad
和变量一样,对象创建后也需要进行初始化。对象的初始化过程是通过调用定义的后者内置的构造函数实现的。
\qquad
构造函数是C++中定义的一种专门用来初始化对象的特殊函数,构造函数的名字与类名完全相同,没有返回值和返回类型,Void也不能写,当对象被创建时,构造函数会被自动调用来初始化对象。
四、析构函数
\qquad
析构函数的主要功能是在程序结束前完成对象的销毁工作。
\qquad
如果在构造函数中使用new为对象分配了内存空间,则应该在析构函数内使用delete释放内存空间。
\qquad
析构函数和构造函数同样与类同名,但是析构函数名字前面要加上“~”。
class Set
{
public:
Set(const int size);//构造函数
~Set(void)//析构函数
{
delete elemes;
}
private:
int *elems;//指向一个动态数组
}
程序演示
int main(void)
{
Set s1(5);
......
return 0;
}
当创建set类的一个实例化对象s时,会先调用构造函数,为对象s中的数据成员分配空间以及初始化。例如,对elems数据成员分配内存及初始化。在程序结束前,系统调用s的析构函数,释放为elems 分配的内存。析构函数不能像其他成员函数一样被直接调用,只能由系统自动调用。
当对象被动态分配内存空间时应主动定义一个析构函数完成对对象空间的释放。构造函数为对象中的数据成员完成初始化操作,因此构造函数必不可少,而析构函数在程序中同样起着相当重要的作用。如果程序中的内存在使用完后没有得到释放,就很容易造成内存泄漏,会导致应用程序运行效率降低,甚至操作系统崩溃,所以要学会利用析构函数释放系统占用的资源。
注意
对象的析构函数在对象销毁前被调用,不同对象的析构函数调用顺序与其作用域有关。自动对象在离开其作用域时便调用其析构函数,动态对象在使用 delete运算符时调用其析构函数,全局对象在程序运行结束时才调用其析构函数。当作用域相同时,析构函数的调用顺序与构造函数的调用顺序相反。
五、静态成员
静态成员是用static来修饰的成员。
一般情况下,访问成员通过对象来访问的,而不能通过类型直接访问。如果将类成员定义为静态成员则允许使用类名直接访问。
六、友元
为了使类中被设立为私有及保护的成员被其他类或者函数访问,C++引入了友元的概念。
七、this指针
在类的成员函数中引用成员变量的时候,可以使用this指针实现,海指针用来存储对象的实例的地址,因此在类内都可以使用this指针调用数据成员以及成员函数。
八、继承
继承指的是某类实物具有比其父辈事物更一般行的某些特征(或者称为属性)。一个类肯呢个既是基类又是派生类。
继承的一般形式:
class 派生类名: 继承方式 基类名1,继承方式 基类名2,……,继承方式 基类名n
{
派生类成员声明;
};
eg:
1.创建一个twopoint类,形成“twopoint.h”文件
#include <iostream>
using namespace std;
class twopoint //二维空间坐标点类的定义
{
protected:
double x,y;//定义保护变量x、y
public: twopoint(double i, double j):x(i), yi{}//构造函数定义
//下面是成员函数定义
void setX(double NewX){x=NewX;}
void setY(double NewY){y=NewY;}
double getX() const {return x;}
double getY() const {return y;}
};
2.创建一个threepoint类,形成“threepoint.h”文件
#include"twopoint.h"
class threepoint:public twopoint //使用继承定义三维空间点类
{
private:
double z; //定义私有变量
public:
double getZ() {return z;}
void setZ(double NewZ){z= NewZ;}
threepoint(double i, double j, double k):twopoint(i,j){z=k;}//成员函数定义
};
3.主函数调用之前定义的类
#include"threepoint.h"
int main()
{
threepoint d3(3, 4, 5); //创建派生类对象
cout<<"三维对象的坐标是:"<<endl;
cout << d3.getX() << ", " << d3.getY() <<"," <<d3.getZ()<< endl;11
return 0;
}
九虚继承和虚基类
\qquad
C++使用虚继承(VirtualInheritance),解决从不同途径继承的同名数据成员在内存中由不同的备份造成的数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个备份,同一个函数名也只有一个映射。这样既解决了二义性问题,也节省了内存,避免了数据不一致问题。
\qquad
虚基类(把一个动词当成一个名词而已)是虚继承的一个同义词。
\qquad
当在多条继承路径上有一个公共的基类时,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,则可以将这个公共基类说明为虚基类。
虚继承的语法如下:
class派生类:virtual 基类1,virtual 基类2,...,virtual 基类n
{
...//派生类成员声明
};
参考资料:《C++从入门到精通 》第一版 谭玉波主编