C++面向对象程序设计总复习
码字不易,万字总结🌻欢迎收藏,如果觉得有帮助的话求赞💗转发💗关注~
有不当之处,还请评论区指正,帮助完善文章~感激不尽😊
逢考必过~高分喷雾✅面试好运,祝一切顺利!
文章目录
1.构造函数汇总:
//默认的构造函数
Date();
//带默认值的构造函数
Date() {
year = 2020;
month = 2;
day = 14;
}
//带参构造函数
Date(int y, int m, int d) {
year = y;
month = m;
day = d;
}
//初始化表
Date(int y,int m,int d):year(y),month(m),day(d){
}
//结合带默认值的带参构造
Date(int y=2021, int m=5, int d=20) {
year = y;
month = m;
day = d;
}
//带默认值的初始化表
Date(int y=2022,int m=6,int d=10):year(y),month(m),day(d){
}
//拷贝构造函数
//Date test2=test1;时发生拷贝构造,而Date test2; test2=test1;则是先构造再赋值,并不调用拷贝构造函数
Date(const Date &t) {
year = t.year;
month = t.month;
day = t.day;
}
2.析构函数&访问对象方式&对象指针&对象数组:
#include<iostream>
using namespace std;
//构造函数与析构函数:
class Date {
public:
//带默认值的初始化表
Date(int y=2022,int m=6,int d=15):year(y),month(m),day(d){
cout << "构造函数已被调用" << endl;
}
//析构函数
~Date() {
cout << "析构函数已被调用" << endl;
}
//显示日期
void show();
private:
int year, month, day;
};
//在类外定义成员函数
void Date::show() {
cout << year << " " << month << " " << day << endl;
}
int main() {
Date test1(2022, 12, 25);
//对象的访问方式:
test1.show();
Date *p; //定义一个对象指针
p = &test1; //让这个对象指针指向test1对象
p->show(); //通过对象指针访问成员
(*p).show(); //相当于test1.show()
//对象数组:数组中存储多个对象
Date dates[3] = {
Date(2022,5,20),Date(2022,5,21),Date(2022,5,22) };
dates[1].show(); //2022 5 21
//引用:相当于别名,引用起来的二者是等同的
//语法:数据类型 &别名 = 原名
Date &tt1 = test1;
//使用new动态申请一个对象
Date *q = new Date(2022, 12, 19);
q->show();
delete q; //使用new动态申请的空间,使用完之后应该delete释放这片空间
}
3.类对象作为数据成员:
即一个类的对象作为另一个类的成员:
- 其他类对象作为本类数据成员时,其他类对象构造函数先调用,再调用本类构造函数,析构时,析构函数调用顺序相反,(变量存放在栈区空间,先申请的在下面,后申请的在上面,释放时先释放上面,后释放下面)(即先进后出)
#include<iostream>
#include<string>
using namespace std;
//定义一个日期类
class Date {
public:
Date(int y=2005,int m=6,int d=19):year(y),month(m),day(d){
}
void show() {
cout << year << " " << month << " " << day << endl;
}
private:
int year, month, day;
};
//定义一个Person类
class Person {
public:
//构造函数示例1
Person(string n,char g,int a,int y,int m,int d):name(n),gender(g),age(a),birth(y,m,d){
}
//构造函数示例2
/*
Person(string n, char g, int a, int y, int m, int d):birth(y, m, d) {
name = n;
gender = g;
age = a;
}
*/
void show() {
cout << name << " " << gender << " " << age << endl;
birth.show();//在这个程序里,出现两个同名函数show,将发生函数重载
/*
两个重载函数必须在下列一个或两个方面有所区别:
1、函数有不同参数。
2、函数有不同参数类型,
*/
}
private:
string name;
char gender; //w:女(women),m:男(men)
int age;
Date birth; //类对象作为另一个类的数据成员
};
int main() {
Person p1("lena", 'w', 18, 2006, 6, 19); //注意c++里双引号单引号不能乱用
p1.show();
}
4.const关键字:
1.常对象:
-
使用const修饰的对象称为常对象,在定义时必须初始化,且此后不能更改
-
定义格式如下:
- 类名 const 对象名(实参表列) Date const test1(2022,2,14);
- const 类名 对象名(实参表列)const Date test1(2022,2,14);
-
常对象只能调用const类型的成员函数,不能调用非const类型的成员函数,这是为了防止通过调用成员函数改变了常对象中数据成员的值
2.常成员函数:
-
定义格式如下:
- 函数返回类型 成员函数名(参数表列)const { 函数体 }
-
const放在函数参数表列的后面,const是函数类型的一部分,可以与不带const的函数进行重载,当同名的一般函数和常成员函数同时存在时,一般对象调用一般的成员函数,常对象调用常成员函数
-
声明函数以及定义函数都要有const修饰
-
常对象只能调用const修饰的函数,即常成员函数
3.常数据成员:
-
定义格式如下:
- const 数据类型 数据成员名 const int x;
- 数据类型 const 数据成员名 int const x;
-
常数据成员必须初始化,定义对象时通过构造函数的初始化设定初始值,此后不能该表
4.指向对象的常指针:
-
定义格式如下:
- 类名 *const 指针变量名=对象地址 Date *const p=&test1;
-
指向对象的常指针是常量,不得改变指针的指向;但该指针指向的对象的数据成员值是可以改变的
5.指向常对象的指针:
-
定义格式如下:
- const 类名 *指针名; const Date *p;
-
指向常对象的指针是指这个指针所指的对象是不能改变的,但指针是可以改变指向的
-
常对象只能用指向常对象的指针指向它,指向一般对象的指针是不能指向常对象的
-
指向常对象的指针不仅可以指向常对象,也可以指向一般对象,但无论指向谁,都不能通过该指针改变对象的值
6.区分指向对象的常指针&指向常对象的指针:
-
const离指针近,Date *const p=&test1; 则是指向对象的常指针,只是保证指针指向不能改变,但所指的值可变
-
const离指针远(离对象近),const Date *p; 则是指向常对象的指针,指针指向可以改变,但其所指的值不能通过指针更改
7.对象的常引用:
-
定义格式如下:
- const 类名 &引用名; const Date &test1;
-
常引用也只能调用常成员函数
-
常引用作为函数形参时,函数中不能有修改其对应实参中数据成员值的语句
-
常引用作为函数形参时,实参可以是一般对象、常对象、一般引用、常引用
5.static关键字:
1.静态数据成员:
一般用于计数,在定义数据成员前加上static修饰即可, static int count; 特点:
-
定义对象时不会为静态数据成员分配内存空间,它是类中对象共享的数据,为所有类共同拥有
-
静态数据成员具有静态生存期,也因此,必须在类外初始化,初始化时,不需要加关键字static
class Person { public: //类内定义静态成员变量 static int n; }; //类外进行初始化 int Person::m_A = 0;
2.静态成员函数:
- 如果静态函数是公有的,在类外可以直接访问;如果是保护的或私有的,在类外只能通过对象调用公有的成员函数访问
- 静态成员函数是类中所有对象共享的成员函数,既可以通过已定义的任何一个对象或对象指针调用它,也可以通过类名直接调用,也因此静态函数也没有默认的this指针
- 它只能对静态数据成员进行操作,不能访问类的非静态数据成员
6.内联函数inline:
内联函数目的是为了提高函数的执行效率,用关键字 inline 放在函数定义前,(注意是定义而非声明) 即可将函数指定为内联函数,内联函数是将它在程序中的每个调用点上“内联地”展开,假设将 max 定义为内联函数:
inline int max(int a, int b)
{
return a > b ? a : b;
}
/*
则调用:cout<<max(a, b)<<endl;
则在编译时展开为: cout<<(a > b ? a : b)<<endl;
*/
-
调用函数比求解等价表达式要慢得多,在大多数的机器上,调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行
-
有了内联函数,就能像调用一个函数那样方便地重复使用一段代码,而不需要付出执行函数调用的额外开销。很显然,使用内联函数会使最终可执行程序的体积增加。以时间换取空间
-
内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处,就像整个函数体在调用处被重写了一遍一样
-
内联函数中的代码应该只是很简单、执行很快的几条语句。如果一个函数较为复杂,它执行的时间可能上万倍于函数调用的额外开销,那么将其作为内联函数处理的结果是付出让代码体积增加不少的代价,却只使速度提高了万分之一,这显然是不划算的。有时函数看上去很简单,例如只有一个包含一两条语句的循环,但该循环的执行次数可能很多,要消耗大量时间,那么这种情况也不适合将其实现为内联函数
7.友元函数&友元类:
友元让private修饰的变量属性不再绝对的私有.在必要的时候可以使用friend关键字进行修饰访问
1.友元函数:
友元函数提高了程序运行的效率,但是破坏了类的封装性,使用时应该权衡利弊
- 全局函数作为友元函数
//友元函数可以直接访问类的私有成员和受保护的成员
//普通函数作为友元函数(以下使用友元函数求两个矩形面积之和)
#include<iostream>
using namespace std;
class Rect {
public:
Rect(int xx1=0,int yy1=0,int xx2=0,int yy2=0):x1(xx1),y1(yy1),x2(xx2),y2(yy2){
}
friend int add_area(Rect &r1, Rect &r2); //友元函数声明
private:
int x1, y1, x2, y2; //存储矩形顶点(左上,右下)坐标信息
};
int add_area(Rect &r1, Rect &r2) {
return (r1.x2 - r1.x1)*(r1.y2 - r1.y1) + (r2.x2 - r2.x1)*(r2.y2 - r2.y1);
}
int main() {
Rect rect1(3, 4, 5, 7), rect2(6, 8, 16, 18);
cout << "两矩形面积之和为:" << add_area(rect1, rect2); //106
}
- 成员函数作为友元函数
//成员函数作为友元函数:友元函数不仅可以是类外的普通函数,也可以是其他类的成员函数
//下面示例中,Teacher类的成员函数setscore()被声明为Student类的友元函数,setscore()函数可以访问Student中的私有成员score
//修改学生分数
#include<iostream>
#include<string>
using namespace std;
class Student; //提前声明Student类
class Teacher {
public:
Teacher(int i,string n)