C到C++
- linux系统中c语言用gcc运行.c文件,c++用g++运行.cpp文件
- 描述 c++=C+C++标准库
- C++完全兼容C
- C++是一门强类型的编程语言:类型检查严格
- C++有一些优化:struct class union 三个关键字使用可以省略
- c中bool类型是枚举,需要 添加头文件stdbool.h,c++中bool、true、false是关键字
- c++如果要使用c的头文件,就把后缀.h改为把c放在头文件名称的第一个字母
- 例如:#include 就是 #include
- 注意 cstring 和 string是两个东西,前者是C语言的头文件,后者是c++的头文件(使用string定义字符串要引入)
函数的缺省参数
个人理解,就是定义一个默认参数,调用函数没传参时,使用这个默认参数- c语言中函数的形参的值必须等到调用函数的时候,实参赋值给形参
- C++中可以自声明的时候就设置一个缺省(默认)参数,如果没有实参赋值给形参,形参的值就是实参的值。
#include <stdio.h>
/**
* 判断一个整数是否为素数
*
* @param a 需要判断的整数
* @return 返回1表示是素数,返回0表示不是素数
*/
int isSuShu(int a)
{
int flag = 1; // 默认假设a是素数
// 遍历从2到a-1的所有整数,检查是否能整除a
for (int i = 2; i < a; i++)
{
if (a % i == 0)
{
flag = 0; // 如果能整除,则a不是素数
}
}
return flag;
}
/**
* 打印从1到指定数之间的所有素数
*
* @param num 指定的上限数,默认为100
*/
void SuShu(int num = 100)
{
// 遍历从1到num-1的所有整数,判断是否为素数并打印
for (int i = 1; i < num; i++)
{
if (isSuShu(i))
{
printf("%d是素数\n", i);
}
}
}
int main()
{
int a;
scanf("%d", &a); // 从用户输入读取一个整数
SuShu(a); // 打印从1到a之间的所有素数
SuShu(); // 打印从1到100之间的所有素数(使用默认参数)
return 0;
}
语法规定
- 只能在声明的时候写,不能在定义的时候写
- 从右往左,缺省参数必须放在最后面
- 调用的时候是根据类型来区分的
- 和函数重载一起使用时,注意二义性问题
函数重载
个人理解,函数可以重名,并且不会相互覆盖,会通过你调用函数时传入入参的个数,找到与之参数对应的函数- 我们写代码的时候,函数名字一样,参数列表不一样,在编译成机器语言后,会变成不一样的函数
参数列表不同
- 参数个数不同
- 参数类型不同
- 参数顺序不同
- const修饰基本数据类型和不修饰一样,const修饰指针和指针不一样
名字空间 namespace
个人理解,就是一块单独作用域,可以用来定义一些变量、函数、方法这些调用的时候要先暴露才能用- 又叫命名空间
- 为了多人协同方便区分标识符,创建了名字空间,每个人可以有单独的名字空间,名字空间内的标识符不能一样,不同名字空间里的标识符一样可以通过名字空间来区分。
使用
// 定义
namespace mingZiKongJin{
int n=6;
}
// 临时使用
printf("%d", mingZiKongJin::n);
// 暴露名字空间中的某个名字,以后都持续使用
// 暴露整个空间,里面的以后都可以持续使用
输入输出流(io流) iostream
- 相当于c的scanf和printf
动态内存分配
- c语言的动态内存分配是malloc、free
- c++可以使用c的动态内存分配,新增运算符new、delete
- new 搭配delete
- new []搭配delete[]
结构体和this指针
- c++结构体里可以定义函数
- 结构体里的函数,通过this.来访问结构体里的其他变量
类与对象
面向对象编程思想 oop
- 编程 == 数据结构 + 算法
- 数据结构 == 对象 物
- 算法 == 流程 事 成员函数 功能 方法
面向过程编程思想
- 核心是过程
- 描述事物的时候,以流程为核心 数据是附属于流程的
- 实时性要求高,开发团队小。代码复用要求不高,代码量小。
面向对象过程思想
- 描述事物的时候以对象为核心,流程是依附于对象的。
- 实时性要求低,开发团队大,代码复用要求高,代码量大。
面向对象特性
四大特性:
- 抽象
- 封装
- 继承
- 多肽
抽象
类
- 分类的类
- 类是特性的集合
- 特性包括:
- 属性 数据 用成员变量来描述
- 功能 流程 用成员函数来描述
- 是虚的
对象
- 现实世界:先有对象,再抽象出类
- 数字世界:先定义类,再用类构造出对象
- 先有类,再有对象
- c++:支持面向对象,允许用面向过程的思维来解决问题,也允许用面向对象的思维来解决问题。
- 纯面向对象:只允许用面向对象的思维来解决问题。万物皆对象。
class
- class是c++中用来声明的关键字。
- c++中class和struct的区别仅仅在于:
- class里的成员默认私有,struct里的成员默认公有。如果不封装的话,class和struct没有区别
封装
为了对象被创建出来之后,队友不会随便改变某个属性,就有了封装特性。
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Hero
{
string name;
int ph;//血量
int bh;//蓝条
public:
// 函数声明
void init(string name, int ph, int bh);
// 函数声明
void show();
//接口函数
void setPh(int p){ ph = p; }
int getBh(void){ return bh; }
void hit(Hero* pHero){
cout << name << "向" << pHero->name << "打出一招降龙十八掌,耗费10点魔法,打掉"
<< pHero->name << "100点血" << endl;
bh -= 10;
pHero->ph -= 100;
}
};
/**
* @brief Hero::init给hearo类定义的成员函数 初始化英雄对象的属性
*
* 该函数用于设置英雄的名字、血量和魔法值。
*
* @param name 英雄的名字
* @param ph 英雄的血量
* @param bh 英雄的魔法值
*/
void Hero::init(string name, int ph, int bh)
{
this->name = name;
this->ph = ph;
this->bh = bh;
}
/**
* @brief Hero::show给hearo类定义的成员函数 显示英雄的当前状态
*
* 该函数用于在控制台输出英雄的名字、血量和魔法值。
*/
void Hero::show(){
cout << "名字:" << name << endl;
cout << "血量:" << ph << endl;
cout << "魔法:" << bh << endl;
}
int main(){
Hero h1,h2;
h1.init("张无忌", 1000, 100);
h2.init("张三丰", 2000, 50);
h1.show();
h2.show();
cout << "-------------------------------" << endl;
h1.setPh(500);
cout << h2.getBh() << endl;
h1.show();
h2.show();
cout << "-------------------------------" << endl;
h1.hit(&h2);
cout << "-------------------------------" << endl;
h1.show();
h2.show();
cout << "-------------------------------" << endl;
while (1);
return 0;
}
公有 关键字 public
- public修饰的成员,可以通过对象名来访问。就像结构体一样。
私有 关键字 pivate
- private修饰的成员,只能对象的成员访问。不能通过对象名访问。
- 函数中可以访问类的私有成员。
- 如果希望访问一个对象
构造析构
- 构造函数 构造器 对应对象的诞生
- 析构函数 析构器 对应对象的销毁
构造函数
- 每个对象都是个构造函数构造出来的。
- 如果我们定义类的时候没有自定义构造函数,编译器就会帮我们写一个构造函数。这个构造函数因为是缺省定义的,所以叫做缺省构造函数。缺省构造函数没有参数。
- 构造函数名和类名一致。
- 构造函数没有返回类型。
- 构造函数可以有任意个参数。
构造函数重载
- 一个类可以有多个构造函数,构成重载
- 一个类的不同对象可以由不同的构造函数构造而来
- 一个对象有且只有一个构造函数。
析构函数
- 在对象被销毁的时候自动被调用
- 构造函数在对象创建的时候自动被调用
- 析构函数没有返回类型名
C++Day2
类的特殊成员
const
复习C语言中的const
- const修饰普通变量
- 变了只能读访问,不能写访问,必须初始化
const 修饰指针
指针常量:const作用于p,p是常量,*p是变量
常量指针:const 作用于 *p,p是变量,*p是常量
const修饰类里面的值属性
- 语法
const int a; - 赋值的时候,在构造函数中对其赋值需要使用自动传参列表
student(aValue):a(aValue){ }; - 自动传参列表只能在定义的时候写,不在声明的时候写
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
/**
* @class student
* @brief 学生类,包含学生的ID、姓名和成绩信息。
*/
class student
{
private:
const int id; // 学生的唯一标识符,不可修改
const string name; // 学生的姓名,不可修改
int score; // 学生的成绩,可以修改
public:
/**
* @brief 构造函数,初始化学生对象。
* @param id 学生的唯一标识符
* @param name 学生的姓名
* @param score 学生的成绩
*/
student(int id, string name, int score);
/**
* @brief 析构函数,释放学生对象的资源。
*/
~student();
/**
* @brief 显示学生的ID、姓名和成绩信息。
*/
void show()
{
cout << "id:" << id << ",ÐÕÃû:" << this->name << ",³É¼¨:" << this->score << endl;
}
};
/**
* @brief 构造函数实现,初始化学生对象的ID、姓名和成绩。
* @param id 学生的唯一标识符
* @param name 学生的姓名
* @param score2 学生的成绩
*/
student::student(int id, string name, int score2) : id(id), name(name)
{
score = score2;
}
/**
* @brief 析构函数实现,释放学生对象的资源。
* @note 由于id和name是const类型,delete操作在此处是不必要的,且会导致未定义行为。
*/
student::~student()
{
delete &id;
delete &name;
delete &score;
}
/**
* @brief 主函数,创建并显示多个学生对象的信息。
* @return 程序执行成功返回0
*/
int main()
{
student s1(1, "zhangsan", 100);
s1.show();
student s2(2, "lisi", 90);
s2.show();
student s3(3, "wangwu", 80);
s3.show();
return 0;
}
const修饰类里面的函数
- 语法:
int getscore() const { return score; } - 修饰函数内不得改变成员变量
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
/**
* @class student
* @brief 学生类,包含学生的ID、姓名和成绩信息。
*
* 该类用于存储和展示学生的基本信息,包括ID、姓名和成绩。
*/
class student
{
private:
const int id; // 学生的ID,不可修改
const string name; // 学生的姓名,不可修改
int score; // 学生的成绩,可以修改
public:
/**
* @brief 构造函数,初始化学生对象。
* @param id 学生的ID
* @param name 学生的姓名
* @param score 学生的成绩
*/
student(int id, string name, int score);
/**
* @brief 析构函数,释放学生对象的资源。
*/
~student();
/**
* @brief 显示学生的ID、姓名和成绩。
*/
void show()
{
cout << "id:" << id << ",姓名:" << this->name << ",成绩:" << this->score << endl;
};
/**
* @brief 获取学生的成绩。
* @return 学生的成绩
*/
int getscore() const
{
return score;
}
};
/**
* @brief 构造函数实现,初始化学生对象的ID、姓名和成绩。
* @param id 学生的ID
* @param name 学生的姓名
* @param score2 学生的成绩
*/
student::student(int id, string name, int score2) : id(id), name(name)
{
score = score2;
}
/**
* @brief 析构函数实现,释放学生对象的资源。
*/
student::~student()
{
delete &id;
delete &name;
delete &score;
}
/**
* @brief 主函数,创建并展示多个学生对象的信息。
* @return 程序执行成功返回0
*/
int main()
{
// 创建学生对象s1,并展示其信息
student s1(1, "zhangsan", 100);
s1.show();
// 创建学生对象s2,并展示其信息
student s2(2, "lisi", 90);
s2.show();
// 创建学生对象s3,并展示其信息
student s3(3, "wangwu", 80);
s3.show();
// 获取并展示s3的成绩
int value = s3.getscore();
cout << "s3的分数是:" << value << endl;
return 0;
}
static
C里的static
- 修饰变量为静态变量,作用域还是不变,生命周期不会随着函数的消亡而消亡,而是等到程序结束才消亡。
- 限制extern拓展作用域,extern可以把同一个工程中其他文件中的变量作用域拓展到当前文件。
- static就是限制某个变量作用域不能被拓展到其他文件中
类的静态成员变量
语法在类里面 static int n;
类的静态成员必须在类外初始化 int student::total = 0;
- 个人理解,就是类会创造一个所有类创建的变量都共用的一部分数据,类的静态成员变量属于整个类,不属于类的某一个对象,无论是那个对象修改这个静态成员变量,其他对象去访问这个静态成员变量,都是修改后的值。
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
class student
{
private:
const int id;
const string name;
int score;
static int total; // 学生总数
public:
student(int id, string name, int score, int totalValue);
~student();
void show()
{
cout << "id:" << id << ",姓名:" << this->name << ",成绩:" << this->score << ",学生总数:" << this->total << endl;
};
int getscore() const
{
return score;
}
};
student::student(int id, string name, int score2, int totalValue) : id(id), name(name)
{
score = score2;
total = totalValue;
}
student::~student()
{
delete &id;
delete &name;
delete &score;
}
int student::total = 0; // 初始化静态变量值
class teacher
{
private:
public:
static teacher *teacherFn()
{
static teacher teacher;
return &teacher;
}
};
int main()
{
teacher *p = teacher::teacherFn();
teacher *p2 = teacher::teacherFn();
cout << p << "," << p << endl;
return 0;
}
类的静态成员函数
语法 static void test() { cout << n << endl; // 只访问静态成员变量 n }
只能通过类名调用静态成员函数 A::test();,用类生成的对象调用不了
- 类的静态成员函数只能访问类的静态成员,不能访问类的非静态成员。
- 类的静态成员函数可以通过类名来访问,类的非静态成员函数不能通过类名来访问。
- 如果一些类只有功能,可以考虑设置为静态成员函数
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class A
{
public:
int m;
static int n;
A() : m(0) {} // 初始化成员变量 m
void set(int m, int n)
{
this->m = m;
this->n = n;
}
void show()
{
cout << "当前对象的n:" << n << ",m:" << m << endl;
}
static void test()
{
cout << n << endl; // 只访问静态成员变量 n
}
};
int A::n = 1; // 类外初始化
int main()
{
A a, b;
A::test(); // 通过类名调用静态成员函数
a.show(); // 通过对象实例调用非静态成员函数
return 0;
}
引用
- C语言里面讲过引用,动词,意思是使用。引用变量等同于使用变量绑定的内存段。
- C++里面新增的引用是名字。是一种新的类型。是内存段的别名。
- 引用本身不占据内存段,必须初始化。
- 语法:
int m = 10; int& n = m;
引用和指针的区别
- 指针占内存,引用不占内存
- 指针可以改变指向,引用不能
- 引用必须初始化,指针不必
- 指针可以改变类型,引用不能
- 有空指针,没有空引用 共同点:都可以指明某块内存区域,指针要解引用,引用就是直接操作。都有类型。 引用的大小是内存段的大小,指针的大小恒为4(32位计算机)或者8(64位计算机)
拷贝构造
个人理解,类有三个构造器,一个有参构造,一个无参构造,一个拷贝构造
- 例如类名为student,public里的
student()函数就是无参构造。 student(string name)传入参就是有参构造。student(student &stuData)只有一个参数,并且参数类型就是这个类的话就是拷贝构造。- 拷贝构造需要用另一个已经声明的对象去赋值给一个新对象
student s2 = s1;
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
// 无参构造
class A
{
public:
A() {};
};
// 有参构造函数和拷贝构造函数
class student
{
public:
const int id;
const string name;
int score;
static int total; // 学生总数
student(int id, string name, int score, int totalValue);
student(const student &s) : id(s.id), name(s.name) // 拷贝构造函数
{
score = s.score;
total = s.total;
cout << "拷贝构造函数" << endl;
};
~student();
};
student::student(int id, string name, int score2, int totalValue) : id(id), name(name)
{
cout << "构造函数" << endl;
score = score2;
total = totalValue;
total++; // 递增学生总数
}
int student::total = 0;
student::~student()
{
total--; // 递减学生总数
}
int main()
{
A b;
student s1(1, "zhangsan", 100, 1);
student s2 = s1; // 拷贝构造函数
printf("s1.score:%d\n", s1.score); // 修正输出语句
return 0;
}
运算符重载
个人理解,运算符重载就是将本来就有的+、-、*、/、%等自带的运算符,通过自定义的方式进行重写 比如c语言中的+不能将两个字符串相加,通过运算符重载的方式就可以自己自定义一个可以将字符串相加的+
友元(友缘)
- 个人理解,就是当一个给一个类,在定义的时候关联一个类外面功能,可以是函数和类,让外面的函数或者类可以访问和修改类里面的变量
友元函数
在类的public内:friend void setScore(Student &student, int newScore);
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
const string name; // 常量名字
int age;
int score;
public:
// 构造函数
Student(string nameValue, int ageValue, int scoreValue) : name(nameValue) // :name(nameValue)自动传参列表
{
age = ageValue;
score = scoreValue;
}
void show() const // const修饰的函数,不能改变成员变量,只读
{
cout << "Name: " << name << ", Age: " << age
<< ", Score: " << score << endl;
}
// 友元函数:允许外部修改成绩
friend void setScore(Student &student, int newScore);
};
// 定义友元函数:修改学生成绩
void setScore(Student &student, int newScore)
{
student.score = newScore; // 直接访问student的私有属性 score,并修改
}
int main()
{
Student student1("张三", 20, 60); // 名字在初始化后不可修改
student1.show();
setScore(student1, 90); // 通过友元函数设置成绩
student1.show();
return 0;
}
友缘类
在类的public内:friend class teacher;
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
const string name; // 常量名字
int age;
int score;
public:
// 构造函数
Student(string nameValue, int ageValue, int scoreValue) : name(nameValue) // :name(nameValue)自动传参列表
{
age = ageValue;
score = scoreValue;
}
// 友元类:允许外部查看修改成绩
friend class teacher; // 将teacher类声明为友元类
};
class teacher
{
public:
void getStudent(Student &student) const // const修饰的函数,不能改变成员变量,只读
{
cout << "Name: " << student.name << ", Age: " << student.age
<< ", Score: " << student.score << endl;
}
void setStudent(Student &student, int scoreValue)
{
student.score = scoreValue;
}
};
int main()
{
Student student1("张三", 20, 60); // 初始化
teacher teacher1;
teacher1.getStudent(student1);
teacher1.setStudent(student1, 99);
teacher1.getStudent(student1);
return 0;
}