C++基础的回顾

来源:互联网 发布:我国颁布的网络法规 编辑:程序博客网 时间:2024/05/18 01:04

 

类成员有以下3种访问类型:

private: 私有成员,只能被该类中的成员访问

public:公有成员,既可以被该类中的成员访问,也可以被该类外的其他部分访问

protected:保护成员,只有该类和其派生类可以访问

 

this指针:

this指针只能在类内部使用,并指向当前对象本身。

 

函数重载:

函数重载是同名函数的多个实现,只要参数类型不同,或是参数个数不同,函数都可以重载。但是如果函数的参数有默认值,就需要注意是否有与其冲突的函数。

 

构造函数:

构造函数是与类同名的成员函数,没有返回值,可以带有参数,可以重载,访问类型必须为public.当创建一个类对象时会被自动调用。

       如果类中没有定义构造函数,编译程序会自动为类添加构造函数,但是什么都不做。编程过程中通常使用构造函数来完成一些初始化操作。

 

 

 

析构函数:

 

在类对象的销毁由析构函数来完成。析构函数名必须被定义为“~”加上类名。析构函数没有返回值,没有参数,不可重载,访问类型为public.析构函数也是有系统自动调用的。

 

 

静态成员:

 

使用static关键字来表示一个类成员是静态成员。非静态成员属于每个对象,而静态成员属于整个类。访问静态成员方法如下:

1、  定义及操作静态成员

如果静态成员是类的成员变量,那么必须对其进行初始化后才能访问。

Class StaticTest

{

Public:

  

  static int count;               //静态成员,计算当前创建了几个类对象

     

  staticTest()             //当创建对象时,会调用对象的构造函数,使count1

{  

     Count++;   // staticTest::count可以访问静态成员,但是在类内部可以省略StaticTest::

}

~ StaticTest()             //当对象销毁时,会调用对象的析构函数,是count1

 

{  

     Coun--;

}

Static void PrintCount()             / /静态成员函数

 

{

  Printf(“%d”,count);

}

 

};

 

Int StaticTest::count=0; //静态成员变量必须初始化才可以使用这里初始化为0

 

Int main(int argc,char* argv[])

{

StaticTest:: PrintCount();          //先输出当前的对象数

 

StaticTest *p1=new StaticTest;          //创建2个对象

 

StaticTest *p2new StaticTest;

StaticTest ::PrintCount();         //再次输出当前的对象数

 

Delete p1;                           //销毁1个对象

 

StaticTest ::PrintCount();         //再次输出当前对象数

 

Delete p2;

Return 0;

}

程序执行如下:

0

2

1

 

可以看到,静态成员就相当于所有类对象的共享数据

 

2、  操作静态成员的条件

由于静态成员属于整个类,而不属于某个对象。所以在静态成员函数中,只能使用静态成员,而不能使用非静态成员。同时也不能使用this指针。以下代码会提示错误。

Void Print()

{

  Printf(“%d,count);

}

Static void PrintCount()

{

  Print();                    //错误,静态成员访问了非静态成员

  Printf(“%d”,this->count);      //错误,静态成员中不能使用this 指针

 

操作静态成员的条件:

非静态成员函数可以访问静态成员;

静态成员函数不能访问非静态成员

静态成员函数不能使用this指针。

 

继承:

继承不仅减少了代码量,同时在维护过程中如果公共的属性发生变化,只需要修改父类,而不用分别修改派生类。

继承的格式:   class <派生类名>[继承方式public/private/protected] <基类名>

 

子类对象的构造函数:

 

 

当创建一个子类对象时,首先会调用父类的构造函数,然后再调用子类的构造函数。由于创建子类对象时传递给构造函数的参数只能给子类,所以,如果想将参数传递给父类的构造函数,可以在子类的构造函数中传递。

 

例如:

 

在子类构造函数中传递参数给父类构造函数方法是在函数名后添 “:父类名(参数列表)”

StudentPlayBastball(const char* name, const char * home,int age)Student(name,home,age)

 

覆盖父类的方法:

 

子类中可以重新编写父类中的方法,使子类的对象调用函数时,执行自己新的方法。

 

 

虚函数:函数前加有virtual

 

虚函数通常是在使用父类指针操作子类对象时使用,会调用子类的虚函数。

当通过父类指针调用子类对象函数时,如果不是虚函数,则直接使用父类的函数。如果是虚函数,则先看子类是否实现了此虚函数,如果子类实现了此虚函数,则调用子类的函数。否则调用父类的函数。

 

虚析构函数:

 

例子:Parent *pChild = new Child;

      delete  pChild;     // 这里创建的 是子类对象,调用了父类和子类的构造函数,但是delete时,因为pChild是父类指针,所以只调用了父类析构函数,而没有调用子类的析构函数。这会使程序想要在子类析构函数中的一些清理工作不会执行。。

 

所以,一般将析构函数写为虚函数。。。

 

 

类的实现和定义分离:

 

 

有时同时包含同一个头文件会产生重定义编译错误。通常在类的头文件中添加一些宏,用来防止此类被其他页面多次包含,例如:

#ifndef  STUDENT_2007_1_1

#define  STUDENT_2007_1_1

//Student.h  学生类头文件

#include <stdio.h>

Class Student{

…….

…………

};

#endif

代码中的粗体表示,在包含此头文件时,如果是第一次包含,#ifndef STUDENT_2007_1_1

为真,此时定义#ifndef STUDENT_2007_1_1

。并且声明Student类,当再次包含此头文件时,#ifndef STUDENT_2007_1_1

为假,所以Student类不会再次声明。最后#endif结束判断。

 

 

 

STL-标准模板库,方便的数据结构

 

STLc++语言的一部分,其中包含了一些容器类型,例如vector ,list, set,map

还包含了一些算法,例如查找、排序。实际开发中用户不用自己手写数据结构,只用调用STL中相应容器便可以完成所需的功能。STL中的容器都是用模板实现的。

 

STL中这些容器要是使用时,都要添加

#include<set/vector/list/map>

using namespace std;

 

集合set

set具有集合的特性,所有元素是唯一的。其内部是二叉树结构,使set中的元素有序存储起来,同时提高了查询、删除、插入的效率。

insert()函数是在集合中插入一个元素,自动按顺序排列。

erase()是删除一个元素。

参数类型为  需要操作的元素

 

 

向量 vector

vector像是一个数组,可以快速的随机访问数组中每个元素。与数组不同的是,vector的大小可以动态增长。Vector的插入和删除操作在序列尾部进行效率最高。在中间插入或是删除要移动元素,所以效率最低。

push_back()向尾部添加元素,

pop_back()删除最后一个元素。参数为需要操作的元素。

 

vector相似于数组,所以可以利用下标操作内部元素。

Size()函数可以获得元素的个数。

除了下标方式,还可以用vector对应iterator(迭代器)对其进行遍历。迭代器相当于一个指针,

begin()返回vector中第一个元素的迭代器,

end()是末尾的迭代器,此迭代器不指向任何元素。

例子:[所有容器通用的模板]

  vector <int> v;  //创建一个int类型的vector,类似一个int数组

vector<int> ::iterator it;   使用迭代器

for(it=v.begin(); it!=v.end(); it++)

{

   Printf(“%d”, * it);

}

 

 

注意:当用insert()在中间插入元素时,参数是2个,第一个插入的位置,是迭代器(指针类型)。可以用int * t=v.begin(); t=t+n。。这里n是插入的位置值。 (这里如果用v.begin()++是错误的,因为常量指针是不能进行自增、自减操作的。。同理,对于所有常量指针,例如数组首地址指针都不能自减自加。。改正方法就是重新定义一个指针,将原指针赋予新指针,然后对新指针进行操作),第2个参数是元素。 Erase()函数也有2个参数。

 

双端队列deque

dequevector的操作几乎一样,只是双端队列在首尾都可以进行高效操作。

Push_back() push_front();pop_back() pop_front();

 

 

链表 list

 

list实现了数据结构中的链表,与vector或是deque不同,list不能用下标访问元素,只能使用迭代器操作。。 但是list可以高效的对序列中任意位置的元素进行插入和删除操作。

push_back()在尾部插入元素。。

reverse()list倒置

 insert()erase()函数操作与vector一样,2个参数。前者在迭代器指定的元素前插入一个目标元素,后者将迭代器所指向元素删除。

 

 

 

映射 map

map是一个键值对,通过键可以操作值。Map也是采用二叉树形式存储的,但存储顺序是按键进行排序存储的。通过键来查找map中元素是高效的。

map<char* ,int> m;

m[“map”]=10;添加元素10

m [“map2”]=20;

m[“map”]=30;修改键为“map”的值