VC C++程序设计学习总结与心得
- 格式:doc
- 大小:199.00 KB
- 文档页数:23
VC/C++程序设计学习笔记与心得
1、const的基本用法
1.1保护被限制的常量,如:
const int a = 3;
/*a = 4;——错误1*/
不能修改由const修饰的变量的值,且必须被初始化!
1.2便于进行类型检查,如:
const_test(const const_test & a)
{
property1 = a.property1;
property2 = a.property2;
/*a.property1 = 3;——错误2*/
//保护引用的参数,防止意外的修改
}
进行函数参数的保护和提醒
1.3为函数重载提供参考,如:
void print()//print1
{
cout << 1 << endl;
}
char print()const//print2
{
cout << 2 << endl;
return 'a';
}
常函数可以作为区分重载的标准
1.4节省空间,提高效率,避免不必要的内存分配,如:
const定义的变量在内存中只保留一份拷贝,#define定义的常量却有若干份拷贝
1.5修饰指针,如:
int b=1;
const int * const a_ptr = &b;
b = 2;//正确
/* (*a_ptr) = 2;——错误4*/
//不能通过指针修改指向的值
/* a_ptr = &c;——错误5*/
//a_ptr = &b; 错
//定义的常量指针,不能修改指向的地址
第一个const限定不能由该指针去改变被指对象的值,第二个const限定不能改变指针所指的对象
1.6修饰引用,如:
const int &bb = b;
b = 2;//ok
//bb = 2;//error
引用的对象默认就不可以修改,再加上第一个const之后,也不能通过本引用名对其进行修改
1.7修饰类的数据成员
必须在初始化列表中进行初始化或者在类外进行初始化,不能在构造函数的大括号里面进行初始化
2、面向对象与面向过程
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向对象程序的基本特点:抽象、封装、继承、多态。
面向对象的优点:
1结构清晰。使人们的编程与实际的世界更加接近,所有的对象被赋予属性和方法,结果编程就更加富有人性化。
2封装性。减小外部对内部的影响。封装将对象有关的数据和行为封装成整体来处理,使得对象以外的部分不能随意存取对象的内部属性,从而有效地避免了外部错误对它的影响,大大减小了查错和排错的难度。
3 容易扩展,代码重用率高。容易扩展,在大框架不变的情况下很容易就开发出适合自己的功能,实现简单,可有效地减少程序的维护工作量,软件开发效率高。
面向过程的优点:易于经常以只读的方式读取数据
3、构造函数和析构函数 构造函数作用:在对象被创建时利用特定的值创建对象,将对象初始化一个固定的状态。
构造函数在创建时被自动调用。
编译器会自动生成无参数的构造函数,但是一旦你定义了自己的构造函数,系统默认构造函数将失效
拷贝构造函数作用:使用已经存在的一个对象,去初始化一个同类的新对象
拷贝构造函数调用的三种情况:
1、 类对象作为函数的返回值,执行完成返回时
2、 类对象作为函数的形参与实参结合时
3、 用类对象对另一个类对象进行赋值或初始化
析构函数作用:完成对象被删除前的清理工作,释放对象所占有的内存。
析构函数在对象生存期即将结束时被自动调用,且不接受任何参数
构造函数调用顺序:按声明的继承顺序,然后时定义类成员实例的顺序。类内嵌则先调用内嵌对象的构造函数,然后调用本类
析构函数调用顺序与其相反
深拷贝和浅拷贝:
若自动调用默认的拷贝构造函数是浅拷贝,与被拷贝对象共用内存
若想有独立内存,必须进行深拷贝,相当于利用被拷贝对象的成员变量值重新进行构造,如:
CmcArrayOfPoint2::CmcArrayOfPoint2(const CmcArrayOfPoint2 &array)
{
cout << "CmcArrayOfPoint2的拷贝构造函数被调用!" << endl;
this->m_n_num = array.m_n_num;
this->point_ptr = new CmcPoint[array.m_n_num];
for (int i=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、指针与引用
指针本身为unsigned long int类型
const在前为指向常量的指针,const在*后为指针类型的常量
不能声明void的类型的变量,但是可以声明使用void类型的指针,赋值时其他类型的指针可以赋值给void*,但是void指针对其他指针赋值需要进行强制类型转换。
函数指针: 数据类型 (*函数指针名)(形参表)【函数名本身就是函数指针】,如:
void f1(int a);
void f2(int a,int b);
int f3(double a);
void f4(double a);
void (*func_ptr)(double);
double d = 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::get_a; 错误!!
C++标准规定,不能将非静态成员函数名直接赋值给成员函数指针,必须进行取地址运算。
非静态成员函数调用时也必须基于类对象,利用 .* 运算符进行调用,如:
cout << (Ca.*fp)() << ends;
对象指针是指指向对象的指针,this指针是隐含于每一个类的成员函数中的特殊指针(包括构造、析构函数),用于指向正在被操作的对象。
指向非静态数据成员的指针需要被声明为 类型 (类名::*指针名)
指向静态数据成员的指针需要被声明为 类型 *指针名
同理,非静态的数据成员也需要建立在类对象的基础上进行访问
5、静态数据成员和友元
静态数据成员具有静态生存期,可以用类名::标识符进行访问,由该类的所有对象共同维护和使用
必须在文件作用域对静态数据成员进行初始化,如:
int CmcPoint::c_n_count = 0;
//必须进行初始化定义性说明
友元函数是在类中定义的非成员函数(所以也不能引用this指针),如:
friend double get_length(const CmcPoint &p1,const CmcPoint &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 ++();//前置单目运算符重载
Clock& operator++(int);//后置单目运算符重载