VC C++程序设计学习总结与心得Word格式.docx

上传人:b****5 文档编号:19132817 上传时间:2023-01-04 格式:DOCX 页数:27 大小:81.93KB
下载 相关 举报
VC C++程序设计学习总结与心得Word格式.docx_第1页
第1页 / 共27页
VC C++程序设计学习总结与心得Word格式.docx_第2页
第2页 / 共27页
VC C++程序设计学习总结与心得Word格式.docx_第3页
第3页 / 共27页
VC C++程序设计学习总结与心得Word格式.docx_第4页
第4页 / 共27页
VC C++程序设计学习总结与心得Word格式.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

VC C++程序设计学习总结与心得Word格式.docx

《VC C++程序设计学习总结与心得Word格式.docx》由会员分享,可在线阅读,更多相关《VC C++程序设计学习总结与心得Word格式.docx(27页珍藏版)》请在冰豆网上搜索。

VC C++程序设计学习总结与心得Word格式.docx

——错误4*/

//不能通过指针修改指向的值

/*a_ptr=&

c;

——错误5*/

//a_ptr=&

//定义的常量指针,不能修改指向的地址

第一个const限定不能由该指针去改变被指对象的值,第二个const限定不能改变指针所指的对象

1.6修饰引用,如:

constint&

bb=b;

b=2;

//ok

//bb=2;

//error

引用的对象默认就不可以修改,再加上第一个const之后,也不能通过本引用名对其进行修改

1.7修饰类的数据成员

必须在初始化列表中进行初始化或者在类外进行初始化,不能在构造函数的大括号里面进行初始化

2、面向对象与面向过程

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

面向对象程序的基本特点:

抽象、封装、继承、多态。

面向对象的优点:

 

1结构清晰。

使人们的编程与实际的世界更加接近,所有的对象被赋予属性和方法,结果编程就更加富有人性化。

2封装性。

减小外部对内部的影响。

封装将对象有关的数据和行为封装成整体来处理,使得对象以外的部分不能随意存取对象的内部属性,从而有效地避免了外部错误对它的影响,大大减小了查错和排错的难度。

3容易扩展,代码重用率高。

容易扩展,在大框架不变的情况下很容易就开发出适合自己的功能,实现简单,可有效地减少程序的维护工作量,软件开发效率高。

面向过程的优点:

易于经常以只读的方式读取数据

3、构造函数和析构函数

构造函数作用:

在对象被创建时利用特定的值创建对象,将对象初始化一个固定的状态。

构造函数在创建时被自动调用。

编译器会自动生成无参数的构造函数,但是一旦你定义了自己的构造函数,系统默认构造函数将失效

拷贝构造函数作用:

使用已经存在的一个对象,去初始化一个同类的新对象

拷贝构造函数调用的三种情况:

1、类对象作为函数的返回值,执行完成返回时

2、类对象作为函数的形参与实参结合时

3、用类对象对另一个类对象进行赋值或初始化

析构函数作用:

完成对象被删除前的清理工作,释放对象所占有的内存。

析构函数在对象生存期即将结束时被自动调用,且不接受任何参数

构造函数调用顺序:

按声明的继承顺序,然后时定义类成员实例的顺序。

类内嵌则先调用内嵌对象的构造函数,然后调用本类

析构函数调用顺序与其相反

深拷贝和浅拷贝:

若自动调用默认的拷贝构造函数是浅拷贝,与被拷贝对象共用内存

若想有独立内存,必须进行深拷贝,相当于利用被拷贝对象的成员变量值重新进行构造,如:

CmcArrayOfPoint2:

:

CmcArrayOfPoint2(constCmcArrayOfPoint2&

array)

{

cout<

"

CmcArrayOfPoint2的拷贝构造函数被调用!

"

<

this->

m_n_num=array.m_n_num;

point_ptr=newCmcPoint[array.m_n_num];

for(inti=0;

i<

=this->

m_n_num-1;

i++)

this->

get_point(i).set_xy(array.get_point(i).get_x(),array.get_point(i).get_y());

}

前向引用声明总结:

1、不能调用没有实现的类

2、可以以形参形式在内联函数中使用,但不能用于类内实现

3、不能在实现前涉及该类的任何细节

4、指针与引用

指针本身为unsignedlongint类型

const在前为指向常量的指针,const在*后为指针类型的常量

不能声明void的类型的变量,但是可以声明使用void类型的指针,赋值时其他类型的指针可以赋值给void*,但是void指针对其他指针赋值需要进行强制类型转换。

函数指针:

数据类型(*函数指针名)(形参表)

【函数名本身就是函数指针】,如:

voidf1(inta);

voidf2(inta,intb);

intf3(doublea);

voidf4(doublea);

void(*func_ptr)(double);

doubled=1.1;

func_ptr=f4;

(*func_ptr)(d);

//func_ptr=f3;

//错误!

//func_ptr=f2;

//func_ptr=f1;

必须使用时符合函数指针声明时的返回值类型和参数类型。

指向类成员函数的函数指针需要被声明为:

数据类型(类名:

*函数指针名)(形参表)如:

int(A:

*fp)(void)=&

A:

get_a;

int(*f)(void);

//f=A:

错误!

C++标准规定,不能将非静态成员函数名直接赋值给成员函数指针,必须进行取地址运算。

非静态成员函数调用时也必须基于类对象,利用.*运算符进行调用,如:

(Ca.*fp)()<

ends;

对象指针是指指向对象的指针,this指针是隐含于每一个类的成员函数中的特殊指针(包括构造、析构函数),用于指向正在被操作的对象。

指向非静态数据成员的指针需要被声明为类型(类名:

*指针名)

指向静态数据成员的指针需要被声明为类型*指针名

同理,非静态的数据成员也需要建立在类对象的基础上进行访问

5、静态数据成员和友元

静态数据成员具有静态生存期,可以用类名:

标识符进行访问,由该类的所有对象共同维护和使用

必须在文件作用域对静态数据成员进行初始化,如:

intCmcPoint:

c_n_count=0;

//必须进行初始化定义性说明

友元函数是在类中定义的非成员函数(所以也不能引用this指针),如:

frienddoubleget_length(constCmcPoint&

p1,constCmcPoint&

p2);

//返回两个点之间的距离(友元函数)

//不能用const修饰!

尽量传引用?

友元函数说明如下:

1)必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数**的函数原型,友元函数的说明可以出现在类的任何地方,包括在private和public部分;

2)注意友元函数不是类的成员函数,所以友元函数的实现和普通函数一样,在实现时不用"

指示属于哪个类,只有成员函数才使用"

作用域符号;

3)友元函数不能直接访问类的成员,只能访问对象成员,

4)友元函数可以访问对象的私有成员,但普通函数不行;

5)调用友元函数时,在实际参数中需要指出要访问的对象,

6)类与类之间的友元关系不能继承。

类的友元关系说明如下:

(1)友元关系不可继承

(2)友元关系是单向的

(3)友元关系是不可传递的

6、函数的重载和默认形参

定义:

两个以上的函数,具有相同函数名和类似的功能,但是形参的个数和类型不同,编译器在调用时对其进行自动匹配。

(C++语法,C语言不支持重载)

能作为重载的区分:

1、函数的形参个数

2、函数的形参类型

3、常函数的const标识符

待默认形参的函数:

声明时时只能从右向左缺省,而且必须给出缺省值

定义时(实现时)不必给出缺省值

7、运算符重载

运算符重载是指对已有的运算符赋予多重含义,使得同一个运算符作用与不同类型的数据时,导致不同的行为。

可以以友元函数的形式或者类成员函数的形式。

不能重载的运算符:

类属运算符(.)成员指针运算符(.*)作用域运算符(:

)sizeof运算符和

三目运算符(?

关于运算符(++,--)前置后置问题,如

Clock&

operator++();

//前置单目运算符重载

operator++(int);

//后置单目运算符重载

调用时像正常形式调用就行

关于CString的运算符重载(声明部分):

classCMyString

public:

CMyString(inti_n_length=INIT_SIZE);

//默认构造函数

CMyString(constchar*i_c_str);

//含有一个参数的构造函数

CMyString(constCMyString&

i_s_str);

//拷贝构造函数

~CMyString();

//析构函数

CMyStringoperator=(constCMyStringi_s_str);

//重载赋值运算符

CMyStringoperator+(constCMyStringi_s_str);

//重载加法运算符

CMyStringoperator+=(constCMyStringi_s_str);

//重载加等于运算符

friendbooloperator==(constCMyString&

i_s_str1,constCMyString&

i_s_str2);

//重载判断是否相等运算符

voidshow()const;

//打印字符串

private:

char*m_c_path;

//初始地址

intm_n_length;

//当前字符串长度

intm_n_max_size;

//最大的储存空间

};

实现部分(基于<

string.h>

):

CMyString:

CMyString(inti_n_length/*INIT_SIZE*/)//默认构造函数

m_c_path=(char*)malloc(sizeof(char)*i_n_length);

m_c_path[0]='

\0'

m_n_length=0;

m_n_max_size=i_n_length;

CMyString(constchar*i_c_str)//含有一个参数的构造函数

m_n_length=strlen(i_c_str);

m_n_max_size=strlen(i_c_str);

m_c_path=(char*)malloc(sizeof(char)*this->

m_n_length);

strcpy(this->

m_c_path,i_c_str);

CMyString(constCMyString&

i_s_str)//拷贝构造函数

m_c_path=(char*)malloc(sizeof(char)*i_s_str.m_n_max_size);

=i_s_str.m_n_length/*!

!

不是-1!

*/;

m_c_path[i]=i_s_str.m_c_path[i];

m_n_length=i_s_str.m_n_length;

m_n_max_size=i_s_str.m_n_max_size;

~CMyString()

m_c_path=NULL;

m_n_length=0;

m_n_max_size=0;

CMyStringCMyString:

operator=(constCMyStringi_s_str)

free(this->

m_c_path);

returni_s_str;

operator+(constCMyStringi_s_str)

CMyStringc_str(this->

m_n_max_size+i_s_str.m_n_max_size);

c_str.m_n_max_size=this->

m_n_max_size+i_s_str.m_n_max_size;

c_str.m_n_length=this->

m_n_length+i_s_str.m_n_length;

c_str.m_c_path=(char*)malloc(sizeof(char)*c_str.m_n_max_size);

strcpy(c_str.m_c_path,this->

strcat(c_str.m_c_path,i_s_str.m_c_path);

c_str.m_c_path[c_str.m_n_length]='

returnc_str;

operator+=(constCMyStringi_s_str)

m_n_max_size+=i_s_str.m_n_max_size;

m_c_path=(char*)realloc(this->

m_c_path,

sizeof(char)*this->

m_n_max_size);

m_c_path[this->

m_n_length]='

m_n_length+=i_s_str.m_n_length;

strcat(this->

m_c_path,i_s_str.m_c_path);

//需要足够的空间

return(*this);

voidCMyString:

show()const//打印字符串

m_c_path<

booloperator==(constCMyString&

i_s_str2)

//重载判断是否相等运算符

if(i_s_str1.m_c_path==NULL||i_s_str2.m_c_path==NULL)

{

if(i_s_str1.m_c_path!

=i_s_str2.m_c_path)//不同时为空

returnfalse;

}

if(i_s_str1.m_n_length!

=i_s_str2.m_n_length)

returnfalse;

if(strcmp(i_s_str1.m_c_path,i_s_str2.m_c_path)!

=0)

returntrue;

微软的实现方式:

char*strcpy(char*dst,constchar*src)

char*cp=dst;

while(*cp++=*src++)

;

//Copysrcoverdst

return(dst);

}//Microsoft的实现方式

intstrcmp(constchar*src,constchar*dst)

intret=0;

while(!

(ret=*(unsignedchar*)src-*(unsignedchar*)dst)&

&

*dst)

++src,++dst;

if(ret<

0)

ret=-1;

elseif(ret>

ret=1;

return(ret);

char*strcat(char*dst,constchar*src)

while(*cp)

cp++;

//findendofdst

while(*cp++=*src++);

//Copysrctoendofdst

//returndst

8、类的继承和派生

构造函数和析构函数不会被继承

私有继承和protected类型继承会把父类的public成员变成对应的类型,有多个基类(多继承),一个(单继承)

从两个不同基类继承来的同名成员,如果不在本类进行覆盖,直接调用,将会导致二义性,编译无法通过,需要利用作用域运算符,会有两份内存分配。

默认为私有继承。

公有继承:

public和protected类属性不变,private类被隐藏,不能直接进行调用。

保护继承:

public和protected类以protected类的属性出现,私有成员不能直接访问。

私有继承:

public和protected类以private类的属性出现,私有成员不能直接访问。

构造派生类对象时,就要对基类数据成员、新增数据成员和成员对象的数据成员进行初始化。

9、虚基类、虚函数、纯虚函数

将继承中的共同基类设置成虚基类,这时从不同路径继承来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射,不会出现二义性。

如:

classCmcBird:

virtualpublicCmcAnimal

//将CmcAnimal视为虚基类

classCmcHorse:

classCmcFlyHorse:

publicCmcBird,publicCmcHorse

如果使用非默认形式的构造函数,在整个继承关系中,直接或者间接继承虚基类的所有派生类,都必须在构造函数初始化列表中给出初始化。

虚函数是动态绑定的基础,且必须是非静态的成员函数。

(如果认为该类会被继承,最好声明其方法为虚函数,但是需要生成虚函数列表,会一定程度上影响性能)

通俗来看,如果一个基类成员函数不是虚函数的话,其派生类将该成员函数覆盖后,利用该基类的指针(或引用),即使指向(引用)的是一个派生类的实例,也只能对基类的函数进行调用。

CmcAnimal*animal=newCmcAnimal;

CmcAnimal*bird=newCmcBird;

CmcAnimal*horse=newCmcHorse;

animal->

move();

horse->

bird->

其中CmcBird、CmcHorse类分别继承了CmcAnimal类,并覆盖了其move()方法,如果在CmcAnimal类中,move()不是虚函数,运行结果为:

如果用virtual标识符对CmcAnimal的move函数进行声明(定义时不必加),即:

virtualvoidmove();

//动物的移动函数

运行结果为:

即基类指针分别正确调用了子类的move()方法

注意:

不能声明类的虚构造函数,析构函数可以,用来指向性清理

抽象类是为了抽象和设计为目的建立的,不能实例化其本身,只能实例其非抽象派生类。

抽象类带有纯虚函数。

纯虚函数是特殊的虚函数(比虚函数还虚……),声明举例如下:

virtualvoidmove()=0;

//动物的移动函数,纯虚函数,必须进行覆盖

声明了纯虚函数后,基类中就不必给出其实现部分【试了一下,给出实现部分也能编译通过,但是没有任何实际意义,因为子类肯定会覆盖它】,函数体由派生类给出。

因为你无法使用基类指针指向基类,如:

//CmcAnimal*animal=newCmcAnimal;

//error因为包含纯虚函数,因此CmcAnimal是一个抽象类

所以无法通过指针调用纯虚函数在基类中的实现,因此完全没有意义。

但是你可以声明抽象基类的指针指向非抽象子类,这是正确的,而且能调用正确的方法:

但是但是,如果通过这种方法:

CmcHorsehorse2;

horse2.CmcAnimal:

//ok!

可以利用作用域进行直接调用,虽然是纯虚函数,但是可以被调用!

//不过既然作为纯虚函数,有定义应该是件不适合的事情

强行通过子类实例的作用域运算符对其调用,可以使用该纯虚函数!

——非常有趣

这样做未免有点过于较劲了,而忽略了纯虚函数的抽象类的目的,只有你绝对肯定不需要使用该类的对象和其成员方法时,你才会将其声明为抽象类和纯虚函数。

最后,如果一个类由抽象类派生,但没有

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 动物植物

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1