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


    一、类

    1.定义成员函数

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

    #include
    #include
    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
    #include"tdate.h"//文件名名称
    using namespace std;
    void TDate::Set(int y,int m,int d){
    	//....
    } 
    

    2.调用成员函数

    1)指针

    #include
    #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
    #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
    #include
    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
    #include
    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
    #include
    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
    #include
    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
    #include
    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 在构造函数体执行之前就已经被初始化为 i
    		Myclass(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
    #include
    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
    #include
    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
    #include
    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
    #include
    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
    #include
    using namespace std;
    
    int id = 0;
    class SId{
    	private:
    		int value;
    	public:
    		SId(int id = 0){
    			cout<<"构建值="<

    输出:

    构建值=9999
    ABC 10000
    销毁id

    五、静态成员变量

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

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

      #include
      #include
      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
    #include
    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<

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

    #include
    #include
    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
    #include
    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<

总结

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

七、继承

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

#include
#include
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();//6
	gs.addCourse(1,4.0);
	cout<<gs.getGpa()<<endl;//3
	gs.Print();//3
}

输出:

Leo 6.5
3
NoName 3

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

继承后面可以不看,了解

1.继承和组合

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

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

2.多继承

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

#include
#include
using namespace std;
class Bed{
	protected:
		int weight;
	public:
		Bed(){
			weight = 0;
		} 
		void Sleep(){
			cout<<"Sleeping"<

输出:

Watching
Folding
Sleeping
20

3.虚拟继承

还很少见 vritual

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

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

床:睡觉

沙发:看电视

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

#include
#include
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"<

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

先虚拟后对象,再自己

八、多态

#include
#include
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: 1
    c++; // 后缀自增
    c.display(); // 输出: Count: 2
    return 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 + 6i
    return 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;
        else
            cout << "Empty string" << endl;
    }
};

int main() {
    MyString s1("Hello");
    MyString s2;
    s2 = s1;
    s2.display(); // 输出: Hello
    return 0;
}
  • 相关阅读:
    swiper在动态创建dom过程中的问题:数据从后端请求回来后加载到页面上,dom加载完发现swiper没用了
    MATLAB——径向基神经网络预测程序
    【MySQL从入门到精通】【高级篇】(二十二)慢查询日志分析,SHOW PROFILE查看SQL执行成本
    Ubuntu20.04下安装nvidia驱动
    视频号视频怎么保存到手机,视频号视频怎么保存到手机相册里,苹果手机电脑都可以用
    VRRP的工作原理和实验详解
    【C++】格式与实例化操作——[模板]详解(7)
    大数据ClickHouse进阶(六):Distributed引擎深入了解
    React组件的生命周期
    【TensorFlow1.X】系列学习笔记【基础一】
  • 原文地址:https://blog.csdn.net/Brittney27/article/details/139885077