zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++基础

2023-09-11 14:20:39 时间

推荐速成视频

c++面向对象编程速成!90分钟搞定
复习100分钟拿下100分,你能做得到吗?【C++】(面向对象程序设计)

一、数据的输入输出

在这里插入图片描述

cin:输入

对于不怎么熟悉或者刚入门C++不久的人来说,cout和cin的箭头方向确实有时候挺容易搞混的,如果隔断时间不用C++,可能都不知道箭头方向到底是指向那边的了。
今天我就带来一种轻松简单的理解记忆方法。

cout的时候,把cout理解成屏幕或者显示器之类的,那么,打印的东西肯定是要输出到屏幕上的, 这样子,箭头肯定是从双引号指向屏幕的,也就是指向cout的。从双引号输出到屏幕,例如:

cout << "hello world!!!" << endl;

cin的时候,把cin理解成键盘,那么,键盘是作为输入字符的东西,因此,箭头肯定就是从键盘,也就是cin指向变量的。例如:

int a;
cin >> a;

希望这种方式能帮助你更好的记忆。THX


cin.getline():读取一行内容

cout:输出


I/O格式控制

设置域宽为5个字符:setw(5)
设置保留小数点后2位有效数字:setprecision(3)

#include <iomanip>
cout<<setw(5)<<setprecision(3)<<3.1415<<endl;

在这里插入图片描述



二、C++函数重载

函数重载:相同函数名和返回值,但参数不同。称为函数重载,只有C++支持,C语言并不支持函数重载。


#include <stdio.h>
//#include <cstdio>
//#include <iostream>
//using namespace std;

int ret(int a){
    return a;
}

int ret(int a,int b){ //函数重载
    return a+b;
}

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d ",ret(a));
    printf("%d ",ret(b));
    printf("%d\n",ret(a,b)); 
    return 0;
}

输入:1 2
输出:1 2 3




三、类和对象

定义类:①数据成员 ②成员函数 ③访问权限


1.struct与class

(1)struct与class的区别

结构体struct和类class都是用来存储多个变量的,两者的用法的差不多,但存在一下区别:
1.类型不同:struct是值类型,而class是引用类型。
2.公有私有:struct中全部成员必须为public,class中默认的成员访问权限是private,可以设置公有还是私有。(没有private的类相当于结构体)
3.能否继承:struct不能被继承,而class可以被继承。

(2)struct与class的相同点

1.C++中,结构体和类中都可以有成员函数



(3)值类型和引用类型

值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中。

1.值类型
值类型(value type):byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。值类型变量声明后,不管是否已经赋值,编译器为其分配内存。

2.引用类型
引用类型(reference type):string 和 class统称为引用类型。当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。



1.如何使用class/struct的成员函数:创建对象,调用方法

直接使用类的成员函数会报错。
必须要实例化一个对象,类的对象才能调用类/结构体的成员函数。


错例:

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

struct Student{
    int age;
    string name;
    int add(int a,int b);
};

int Student::add(int a,int b){
    return a+b;
}

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    cout<<Student::add(a,b);   //这句会报错
    return 0;
}

改正:创建对象,对象调用成员函数

Student stu;
cout<<stu.Student::add(a,b);


2.类的成员函数和成员数据的正规写法

方法放在public中,属性放在private中。防止外部直接修改数据。
在这里插入图片描述



四、成员函数

在这里插入图片描述

1.构造函数

1.构造函数的本质:每个对象的默认初始化。
创建对象的时候会调用构造函数。如果每个对象都需要相同的初值,若将初值写在构造函数里,就不必为每个对象显式地写初值了。


不带参数的构造函数、带参数的构造函数:
创建对象时不带参数,调用不带参数的构造函数。初始值赋予默认值;
创建对象时对象有括号带参数,则调用带参数的构造函数。初始值一般赋予传进去的参数。

#include <cstdio>
#include <iostream>
using namespace std;

class Student{
public:
    int age;
    string name;
    Student(); //构造函数
    Student(int a,string n);
};

Student::Student(){
    age = 24;
    name = "Edward";
    cout<<"Student()"<<endl;
}

Student::Student(int a,string n){
    age = a;
    name = n;
    cout<<"Student(age,name)"<<endl;
};


class Postgraduate:public Student{
public:
    string reserach;
    Postgraduate();
    Postgraduate(string re);
    Postgraduate(int a,string n,string re);
};

Postgraduate::Postgraduate(){
    reserach = "CS";
    cout<<"Postgraduate()"<<endl;
}

Postgraduate::Postgraduate(string re){
    reserach = re;
    cout<<"Postgraduate(string re)"<<endl;
}

Postgraduate::Postgraduate(int a,string n,string re):Student(a,n){
    reserach = re;
    cout<<"Postgraduate(int a,string n,string re)"<<endl;
};

int main(){
    Postgraduate a("计算机");
    cout<<a.age<<endl<<a.name<<endl<<a.reserach<<endl<<endl;

    Postgraduate c(21,"小王","机械");
    cout<<c.age<<endl<<c.name<<endl<<c.reserach;
    return 0;
}

输出:

Student()
Postgraduate(string re)
24
Edward
计算机

Student(age,name)
Postgraduate(int a,string n,string re)
21
小王
机械


2.拷贝构造函数

1.定义
用赋值的方式,为新对象初始化时,调用拷贝构造函数

Student stu2 = stu1; 

2.格式

类名(const 类名 & 对象名)



3.析构函数

2.析构函数:释放堆空间

4.常成员函数 const

安全起见,防止在该函数中出现修改数据的情况。一般用于只读函数。


#include <iostream>
#include <string>
using namespace std;

class Student{
public: //声明public,否则class默认private,在main函数中无法调用
    int age;
    string name;
    bool read() const;
    Student();      //构造函数的声明
};

Student::Student(){ //构造函数的实现
    age = 24;
    name = "Edward";
}

bool Student::read() const{  //加const是为了安全起见,防止该函数后续被写入赋值语句
    cout<<"age:"<<age<<endl;
    cout<<"name:"<<name<<endl;
    //age = 25;  //会报错
}

int main(){
    Student stu; //创建对象
    stu.read();
    return 0;
}

在const里修改数据会报错:
【Cannot assign to non-static data member within const member function ‘read’
【在const成员函数read中不能给非静态数据成员赋值】


5.静态成员 static

描述全局,与类有关,又与某个对象属性无关的,叫做静态成员数据。读取静态成员数据的方法,叫做静态成员函数

静态成员数据:静态成员数据只能由静态成员函数读取。
静态成员函数:不依赖于对象。


例:静态成员变量需要在类外进行初始化
int Student::cnt = 0;

#include <cstdio>
#include <iostream>
using namespace std;

class Student{
public:
    int age;
    string name;
    Student(); //构造函数
    static int cnt; //统计对象个数
    static int count();
};

Student::Student(){
    age = 24;
    name = "Edward";
    cnt++;
}

int Student::cnt = 0; //静态成员变量需要在类外初始化

int Student::count(){  //这里不写static
    return cnt;
}

int main(){
    Student a;
    Student b;
    cout<<Student::count();
    return 0;
}




五、继承

1.子类会自动继承父类的属性和方法。只需要写继承方式和自己新增的成员。
继承时,会首先调用基类的构造函数,再调用派生类的构造函数

在这里插入图片描述

2.继承方式:
①public:所有人都能访问
②protected:只有自己和子类能访问
③private:只有自己能访问
在这里插入图片描述



六、多态

1.覆盖

1.重载:同返回值、同名的函数,却有不同的参数。在C++中当作不同的函数
2.隐藏(Hiding):父类与子类函数同名,可以有不同参数,父类的该函数被隐藏,默认调用子类的,而看不见父类的
3.覆盖(Overriding):子类与父类有同名的虚函数。

重载是编译时决定,多态是运行时决定。

在这里插入图片描述

在这里插入图片描述


2.虚函数、类指针

virtual

在这里插入图片描述


3.纯虚函数、抽象类

在这里插入图片描述
在这里插入图片描述



七、C++内存:堆内存区、栈内存区

在这里插入图片描述



八、循环

1.foreach

foreach(variable,container)

foreach(QPushButton *pBtn,btnpVec)
{	
}

2.iterator

迭代器

QVector<QPushButton *>::iterator it;
for(it = btnVec.begin();it != btnVec.end();it++)
{
}

3.auto


4.for、while



九、宏

1.INT_MAX:C++中表示+∞的宏。需要加入头文件

#include <climits>



十、编程思想

类,只管自己的事情



十一、常见的坑

1.传参进去的函数,main中要声明变量,接收,函数返回值
先在调用函数前面声明并初始化实参,main函数里传参的时候不带实参类型,函数里实现的时候要写形参类型

传入实参不带类型,接收时形参要带参数类型

int main(){
	int a = 1,c;
	c = life(a);  //c用于接收life()的返回值,否则返回值会走丢
}


2.含参函数声明和实现的时候,括号里要带参数类型。(否则报错unknown type name ‘形参名’)

int life(int b){    //形参名b可以不与实参名a相同,但是要写参数类型
 
}

返回值类型 函数名(形参类型 形参名){ 函数体}

甚至形参类型不与实参类型相同,函数体里也照样按照实参的类型来运算。

在main函数里要有变量接收函数的返回值。

1.和2.完整代码:

#include <iostream> 
using std::cout;
using std::endl;
  
//参数生命周期
int life(float c){  //接收参数,要写函数返回类型和形参类型 
	int d = c +1.5;
    return d;
}
  
int main()
{
    int a=1,b;
    b = life(a);//传入参数,不写函数类型和实参类型。main中要有变量接收函数返回值
    cout <<"b:"<<b<<endl;
    return 0;                                                           
}

输出:
b:2