欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 大二C++期末复习(自用)

大二C++期末复习(自用)

2024/12/1 0:47:29 来源:https://blog.csdn.net/Brittney27/article/details/139885077  浏览:    关键词:大二C++期末复习(自用)

一、类

1.定义成员函数

输入年份判断是否是闰年,若是输出年份;若不是,输出NO

#include<iostream>
#include<cstring>
using namespace std;
class TDate{private:int month;int day;int year;public:TDate(int y,int m,int d){year = y;month = m;day = d;}void IsLeapYear(){if((year%400 == 0 )||(year%4==0&&year%100!=0)) {this->Print()	;}else cout<<"No"<<endl;}void Print(){cout<<"Yes"<<endl;cout<<year<<"/"<<month<<"/"<<day<<endl;}
}; 
int main(){int y,m,d;cin>>y>>m>>d;TDate s(y,m,d);s.IsLeapYear();return 0;
}

2.定义头文件,使用类的接口

成员函数定义看作类的内部,如private的变量定义和public成员函数的声明

//文件名:tdate。h
//预编译处理器
#ifndef TDATE//if not define TDATE将会定义
#define TDATE//定义TDATE
class TDate{
private:int year;int month;int day;
public:void Set(int int int);void IsLeapYear();void Print();
};
#endif

上述是一个tdate.h的类定义 -> 接口

//tdate.cpp 实现类---成员函数的定义
#include<iostream>
#include"tdate.h"//文件名名称
using namespace std;
void TDate::Set(int y,int m,int d){//....
} 

2.调用成员函数

1)指针

#include<iostream>
#include"tdate.h"//文件名名称
using namespace std;
void somefuc(TDate *ps){ps->IsLeapYear();//调用指针输出判断 
}
int main(){TDate s;s.Set(1983,2,3);somefuc(&s);
}

2) 引用

#include<iostream>
#include"tdate.h"//文件名名称
using namespace std;
void somefuc(TDate &ps){ps->IsLeapYear();//调用指针输出判断 
}
int main(){TDate s;s.Set(1983,2,3);somefuc(s);
}

**注意区别指针和引用 大部分情况下是相同 **但指针要给新变量分配空间,而引用直接给原来的地址

3.总结

1.应用1为输入年份,应用2是计算点的直角坐标和极坐标

2.掌握实现类的定义 tdate.h 类的实现 tdate.cpp(成员函数定义)

二、构造函数

1.默认构造函数

class Student{private:char name[10];  
}; 
int main(){Student s;
}

2.无参构造函数

构造函数可以直接调用print

#include<iostream>
#include<cstring>
using namespace std;class Desk{private:int weight;int high;int width;int length;public:Desk(){weight = 20;high = 10;width = 90;length = 100;print();}void print(){cout<<weight<<" "<<high<<" "<<width<<" "<<length<<endl;}
};
int main(){Desk d;
}

3.传参构造函数

见1.1(常见)

4.重载构造函数

1.重载过程中参数个数不一样才能构造成功

2.在构造无参传递过程中,不用加(),如

Student s( ); —error 不用加括号


#include<iostream>
#include<cstring>
using namespace std;class Student{private:int grade;float gpa;int num;public:Student(){grade = 100;gpa = 5.0;num = 123;cout<<grade<<" "<<gpa<<" "<<num<<" "<<endl;}Student(int s,float g){grade = s;gpa = g;num = 456;cout<<grade<<" "<<gpa<<" "<<num<<" "<<endl;}Student(int s){grade = s;gpa = 3.6;num = 789;cout<<grade<<" "<<gpa<<" "<<num<<" "<<endl;}
};int main(){Student s1;Student s2(90,4.7);Student s3(80); 
}

5.嵌套构造函数

main函数开始运行,创建Pair对象p,调用Pair构造函数,为private变量分配空间(int变量,Student,Teacher),最后执行自己的public钟的成员函数,

一步一步的执行

**private 成员变量会在 public 成员函数之前分配空间**

#include<iostream>
#include<cstring>
using namespace std;class Student{private:int grade;float gpa;public:Student(){grade = 100;gpa = 5.0;cout<<grade<<" "<<gpa<<" "<<endl;}
};
class Teacher{private:int salary;public:Teacher(){salary = 30000;cout<<salary<<endl;}
};
class Pair{private:int meeting;
//组合Student s;//创建2 Teacher t;//创建3 public:Pair(){meeting = 0;cout<<meeting<<endl;}
};
int main(){Pair p;//创建1 
}

6.拷贝构造函数

一般拷贝构造函数的结构

Student (Student &s) //有一个&

1)使用指针

当private里面是指针时,使用new分配空间 strcpy()

#include<iostream>
#include<cstring>
using namespace std;
class Person{private:char *name;public:Person(char *pname){name = new char[strlen(pname) + 1];if(pname != 0)strcpy(name,pname);cout<<"构造:"<<endl;}//自定义拷贝构造函数 Person(const Person &other){name = new char[strlen(other.name) + 1];if(other.name != 0 )strcpy(name,other.name);cout<<"拷贝:"<<endl; }const char* getName( )const{return name;}~Person(){delete[] name;}
};
int main(){Person p1("A");Person p2(p1);// 等价于p2 = p1;cout<<p2.getName()<<endl; 
}

输出

构造:
拷贝:
A

2)使用数组

直接复制 ,不用分配空间和删除空间 strncpy()

#include<iostream>
#include<cstring>
using namespace std;
class Person{private:char name[40];public:Person(char *pname = "NoName"){strncpy(name,pname,sizeof(name));name[sizeof(name) - 1] = '\0';cout<<"构造:"<<endl; }//自定义拷贝构造函数 Person(const Person &other){strncpy(name,other.name,sizeof(name);name[sizeof(name) - 1] = '\0';cout<<"拷贝: "<<endl;}const char* getName( )const{return name;}~Person(){delete name;}
};
int main(){Person p1("A");Person p2(p1);cout<<p2.getName()<<endl; 
}

3) 区别strcpy和strncpy

strcpy () 完整的将数组进行复制

strncpy()对于数组中位置多的元素,使用’\0’ 进行填充,否则就全部复制,但常常与 name[sizeof(name) - 1 ] = '\0 连用,保证结尾为空字符,字符串完整

7.关于类的数据成员初始化

对于类的数据成员是一般变量的情况,放在冒号后放在函数体中的初始化是一样的

1)赋值操作有两次初始化

class Myclass{private:int d;public:Myclass(int i){d = i;}
}; 

2)成员初始化列表

class Myclass{private:int d;public:
//成员初始化列表
//d 在构造函数体执行之前就已经被初始化为 iMyclass(int i) : d(i){}
}; 

常常使用于常量和引用变量,因为

它们必须再被声明的同时进行初始化,它们**不能**在之后被赋值。这意味着你不能先声明一个常量或引用变量,然后再给它赋值

class MyClass {
private:const int myConst;int& myRef;
public:MyClass(int value, int& refValue) : myConst(value), myRef(refValue) {// 构造函数体}
};

相当于进行一次初始化,构造函数的参数值给到后面: 成员的()值中。

class StudentID{int value;public:Student(int id = 0){value = id;}
};
class Student{private:char name[20];StudentID id;public:Student(char *pname,int ssID = 0):id(ssID){//...}
};

三、析构函数

1.析构过程

无返回类型 无参数 生命周期结束后自动调用

析构函数和调用构造函数的相反顺序(栈)

#include<iostream>
#include<cstring>
using namespace std;class Student{private:int grade;float gpa;public:Student(){grade = 100;gpa = 5.0;cout<<grade<<" "<<gpa<<" "<<endl;}~Student(){cout<<"销毁学生类"<<endl; }
};
class Teacher{private:int salary;public:Teacher(){salary = 30000;cout<<salary<<endl;}~Teacher(){cout<<"销毁老师类"<<endl; }
};
class Pair{private:int meeting;Student s;//创建2 Teacher t;//创建3 public:Pair(){meeting = 0;cout<<meeting<<endl;}~Pair(){cout<<"销毁配对类"<<endl; }
};
int main(){Pair p;//创建1 
}

输出 :

100 5
30000
0
销毁配对类
销毁老师类
销毁学生类

2.外部定义成员函数

使用 :: 进行设置


#include<iostream>
#include<cstring>
using namespace std;class Student{private:int grade;float gpa;int num;public:Student();void Print();
};
Student::Student(){grade = 100;gpa = 4.2;Print();
};
void Student::Print(){cout<<grade<<" "<<gpa<<" "<<endl;
}
int main(){Student s;
}

四、综合应用(1)

1.学生姓名 和 学号构造


#include<iostream>
#include<cstring>
using namespace std;class Student{private:char name[20];int num;public:Student(char*,int);void Print();
};
Student::Student(char* pname ,int n){num = n;strncpy(name,pname,sizeof(name));name[sizeof(name) - 1] = '\0';Print();
};
void Student::Print(){cout<<name<<" "<<num<<" "<<endl;
}
int main(){Student s("AAB",1);
}

若构造函数传递过程中不提供任何值,则为默认值和python的函数传递有点像

Student::Student(char* pname = "NoName" ,int n = 0){num = n;strncpy(name,pname,sizeof(name));name[sizeof(name) - 1] = '\0';Print();
};//输出:NOName 0

2,学生姓名 和 学号构(进阶)

定义两个类,进行嵌套使用


#include<iostream>
#include<cstring>
using namespace std;int id = 0;
class SId{private:int value;public:SId(int id = 0){cout<<"构建值="<<id<<endl; value = ++id;}~SId(){cout<<"销毁id"<<endl;value = --id;}int GetValue(){return value;}
};class Student{private:char name[20];SId id;//分配变量空间  public:Student(char*,int);void Print();
};
Student::Student(char* pname = "NoName" ,int n = 0){
//无参传递为默认值strncpy(name,pname,sizeof(name));name[sizeof(name) - 1] = '\0';SId id(n);//传入值 Print();
};
void Student::Print(){cout<<name<<" "<<id.GetValue()<<" "<<endl;
}
int main(){Student s("ABC",2);
}

输出:

构建值=0
构建值=2
ABC 1
销毁id
销毁id

上面的方法,初始化浪费空间,

****(常用)****下面在初始化其他类对象时,直接给其他类变量赋值,不用再次申请多余的变量空间

注意使用一个: 进行初始化对象


#include<iostream>
#include<cstring>
using namespace std;int id = 0;
class SId{private:int value;public:SId(int id = 0){cout<<"构建值="<<id<<endl; value = ++id;}~SId(){cout<<"销毁id"<<endl;value = --id;}int GetValue(){return value;}
};class Student{private:char name[20];SId id;//分配变量空间  //该处不能初始化其他类的对象 public:Student(char*,int);void Print();
};
Student::Student(char* pname = "NoName" ,int n = 0) :id(n){strncpy(name,pname,sizeof(name));name[sizeof(name) - 1] = '\0';Print();
};
void Student::Print(){cout<<name<<" "<<id.GetValue()<<" "<<endl;
}
int main(){Student s("ABC",9999);
}

输出:

构建值=9999
ABC 10000
销毁id

五、静态成员变量

静态成员函数和静态成员变量都是属于类并非属于一个对象(类的实例 ) 可以直接通过对类名进行访问

  • 声明和定义是分开的。静态成员变量在类的定义中声明,在类外部进行初始化

    #include<iostream>
    #include<cstring>
    using namespace std;class Student{static int noOfStudent;char name[40];public:Student(char* pname="no name"){strncpy(name,pname,40);name [39] = '\0';noOfStudent ++;//1}~Student(){cout<<"销毁"<<endl;noOfStudent--;}static int number(){return noOfStudent;}
    };
    int Student::noOfStudent = 0;void fn(){Student s1;cout<<"s1构造完毕"<<endl;Student s2;cout<<"s2构造完毕"<<endl;cout<<Student::number()<<endl;
    }
    int main(){fn();cout<<"主函数输出:";cout<<Student::number<<endl;
    }
    

输出:

s1构造完毕
s2构造完毕

2

销毁

销毁

主函数输出:0

六、友元函数

#include<iostream>
#include<cstring>
using namespace std;class Person{private:int age;public:Person(int age){this->age = age;}friend void showAge(Person &p);
};
void showAge(Person &p){cout<<p.age<<endl;
}
int main(){Person p(10);showAge(p);
}

下面两个为使用友元函数和不使用友元函数的对比

#include<iostream>
#include<cstring>
using namespace std;class Animal{private:int itsWeight;int itsAge;public:friend void setValue(Animal & ,int);friend void setValue(Animal& ,int ,int); 
};
void setValue(Animal &ta ,int tw)
{ta.itsWeight = tw;cout<<ta.itsWeight<<" "<<endl;
}void setValue(Animal &ta ,int tw ,int tn){ta.itsWeight = tw;ta.itsAge = tn;cout<<ta.itsWeight<<" "<<ta.itsAge<<" "<<endl;}int main(){Animal c1,c2;setValue(c1,123);setValue(c2,45,67);}

增加访问类中保护数据的成员函数

#include<iostream>
#include<cstring>
using namespace std;class Animal{private:int itsWeight;int itsAge;public:Animal(int tw,int ta){itsWeight = tw;itsAge = ta; }int getWeight(){return itsWeight; }int getitsAge(){return itsAge;}
};int main(){Animal c1(123,456);cout<<c1.getitsAge()<<" "<<c1.getWeight()<<" "<<endl;}

总结

  1. 使用友元, 可以不用增加访问数据的成员函数
  2. 直接定义友元使用,可以不考虑private、和protected的性质

七、继承

使用学生类进行大学生和研究生的继承

#include<iostream>
#include<cstring>
using namespace std;
class Advisor{int noOfMeeting;
};
class Student{char name[40];float gpa;public:Student(char *pname = "NoName"){strncpy(name,pname,40);name[39] = '\0';gpa = 0;}void addCourse(int hours,float grade){gpa = (hours + 1 + grade) / 2;}float getGpa(){return gpa;} void Print(){cout<<name<<" "<<gpa<<endl;}
};
class GraduateStudent : public Student{private:Advisor teacher;int grade;public:int getGrade(){return grade;}
};
int main(){Student s1("Leo");GraduateStudent gs;s1.addCourse(2,10.0);s1.Print();//6gs.addCourse(1,4.0);cout<<gs.getGpa()<<endl;//3gs.Print();//3
}

输出:

Leo 6.5
3
NoName 3

  • 1.public继承
  • 2.private继承,基类的私有还是私有
  • 3.protected的保护还是保护

继承后面可以不看,了解

1.继承和组合

类以另一个类对象作为数据成员------组合

前面代码中学生和老师共同形成Pair已经遇到了

2.多继承

尽可能不使用,容易产生成员模糊性

#include<iostream>
#include<cstring>
using namespace std;
class Bed{protected:int weight;public:Bed(){weight = 0;} void Sleep(){cout<<"Sleeping"<<endl;}int SetWeight(int i){weight = i;return weight;}
};
class Sofa{protected:int weight;public:Sofa(){weight = 0;}void Watch(){cout<<"Watching"<<endl;}int SetWeight(int i){weight = i;return weight;}
};
class SleeperSofa : public Bed , public Sofa{
//多继承public:SleeperSofa(){} void FoldOut(){cout<<"Folding"<<endl;}
};
int main(){SleeperSofa ss;ss.Watch();ss.FoldOut();ss.Sleep();
//都有输出SetWeight,但要指明类别,否则模糊cout<<ss.Sofa::SetWeight(20);
}

输出:

Watching
Folding
Sleeping
20

3.虚拟继承

还很少见 vritual

区分虚拟函数虚拟继承,二者无任何联

家具: 获取重量 设置重量(床、沙发)

床:睡觉

沙发:看电视

沙发床:折叠 (床、沙发)

#include<iostream>
#include<cstring>
using namespace std;
class Furniture{int weight;public:Furniture(){}void SetWeight(int i){weight = i;}int GetWeight(){return weight;}
};//虚拟继承
class Bed : virtual public Furniture{public:Bed(){}void Sleep(){cout<<"Sleeping"<<endl;}
};
class Sofa : virtual public Furniture{public:Sofa(){}void WatchTV(){cout<<"Watching"<<endl;}
};class SleeperSofa : public Bed,public Sofa{public:SleeperSofa():Sofa(),Bed(){//类成员初始化嵌套 }void FoldOut(){cout<<"Folding"<<endl;}
};
int main(){SleeperSofa ss;ss.FoldOut();ss.WatchTV();ss.Sleep();ss.SetWeight(20);cout<<ss.GetWeight()<<endl;
}

4.继承、组合、虚拟的构造顺序

先虚拟后对象,再自己

八、多态

#include<iostream>
#include<cstring>
using namespace std;
class Base{public:virtual void fn(){cout<<"Base"<<endl;}
}; 
class SubClass : public Base{public:virtual void fn(){//派生类中的virtual可以省略cout<<"Subclass"<<endl;}
};
int i = 0;
void Test(Base & b){b.fn();i++;cout<<"创建完毕"<<i<<endl;
}
int main(){Base bc;SubClass sc;Test(bc);Test(sc);
}

输出

Base
创建完毕1
Subclass
创建完毕2

多态效果 :virtual 虚函数与成员函数完全相同

纯虚函数:被标明,但不具体实现的虚成员函数

virtual void init() = 0

九、运算符重载

1、一元运算符重载(++)

class Counter {
private:int count;
public:Counter(int c = 0) : count(c) {}// 前缀自增运算符重载Counter& operator++() {++count;return *this;}// 后缀自增运算符重载Counter operator++(int) {Counter temp(*this);count++;return temp;}void display() const {cout << "Count: " << count << endl;}
};int main() {Counter c;++c; // 前缀自增c.display(); // 输出: Count: 1c++; // 后缀自增c.display(); // 输出: Count: 2return 0;
}

this指针指向当前函数

2.二元运算符重载(+)

class Complex {
private:double real, imag;
public:Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}Complex operator+(const Complex& c) const {return Complex(real + c.real, imag + c.imag);}void display() const {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(1.0, 2.0);Complex c2(3.0, 4.0);Complex c3 = c1 + c2;c3.display(); // 输出: 4 + 6ireturn 0;
}

++当二元运算符作为成员函数重载时,第一个操作数是调用该函数的对象,第二个操作数通过参数传递。++

3、赋值运算符重载(=):

class MyString {
private:char* str;
public:MyString(const char* s = "") {if (s) {str = new char[strlen(s) + 1];strcpy(str, s);} else {str = nullptr;}}~MyString() {delete[] str;}MyString& operator=(const MyString& s) {if (this != &s) {delete[] str;str = new char[strlen(s.str) + 1];strcpy(str, s.str);}return *this;}void display() const {if (str)cout << str << endl;elsecout << "Empty string" << endl;}
};int main() {MyString s1("Hello");MyString s2;s2 = s1;s2.display(); // 输出: Helloreturn 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com