C++中的类与构造函数

一、C++中类的常用写法

1、在头文件中声明类的属性和方法

如:MyTeacher.h

//防止重复引入
#pragma once
class MyTeacher{
private:
    char* name;
    int age;
public:
    void setName(char* name);
    char* getName();
    void setAge(int age);
    int getAge();
};

2、在源文件中(.cpp)实现对应的方法

如:MyTeacher.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "MyTeacher.h"
#include <iostream>

void MyTeacher::setName(const char* name) {
	this->name = new char[100];
	strcpy(this->name, name);
}

char* MyTeacher::getName() {
	return this->name;
}

void MyTeacher::setAge(int age) {
	this->age = age;
}

int MyTeacher::getAge() {
	return this->age;
}

3、在具体C++代码中使用

如:test.cpp

#include "MyTeacher.h"
using namespace std;

void main() {
	MyTeacher t;
	t.setName("Jack");
	t.setAge(25);
	cout << t.getName() << "," << t.getAge() << endl;
	getchar();
}

二、C++中类的构造函数、析构函数、拷贝构造函数

1、构造函数

  • C++类默认有无参构造函数,重写无参构造函数会覆盖默认的无参构造函数
  • 有参构造函数会覆盖默认无参构造函数
class Teacher{
private:
    char* name;
    int age;
public:
    //无参构造函数
    Teacher(){
        cout << "无参构造函数" << endl;
    }
    
    //有参构造函数
    Teacher(char *name,int age){
        this->name = name;
        this->age = age;
        cout << "有参构造函数" << endl;
    }
};

void main(){
    Teacher t1;
    Teacher t2("Rose",23);
    //有参构造函数另一个调用方式
    Teacher t3 = Teacher("jack",21);
    getchar();
}

2、析构函数

当对象要被系统释放时,析构函数会被调用,一般用作善后处理

class Teacher{
private:
    char* name;
    int age;
public:
    //无参构造函数
    Teacher(){
        this->name = (char*)malloc(100);
        strcpy(name,"Hello,Jack Teacher");
        this->age = 25;
        cout << "无参构造函数" << endl;
    }
    //析构函数
    ~Teacher(){
        cout << "析构函数" << endl;
        free(this->name);
    }
    
    //有参构造函数
    Teacher(char *name,int age){
        this->name = name;
        this->age = age;
        cout << "有参构造函数" << endl;
    }
};

void func(){
    Teacher t1;
}

void main(){
    func();
    
    getchar();
}

3、拷贝构造函数

3.1 浅拷贝

  • 默认拷贝构造函数,就是值拷贝(浅拷贝)
  • 浅拷贝拷贝的是指针的地址(同一块内存区域)
using namespace std;
class Teacher {
private:
	char* name;
	int age;
public:
		//有参构造函数
	Teacher(char *name, int age) {
		this->name = name;
		this->age = age;
		cout << "有参构造函数" << endl;
	}
	//析构函数
	~Teacher() {
		cout << "析构函数" << endl;
		free(this->name);
	}

	//拷贝构造函数
	Teacher(const Teacher &obj) {
		this->name = obj.name;
		this->age = obj.age;
		cout << "拷贝构造函数" << endl;
	}

	void myprint() {
		cout << name << "," << age << endl;
	}
};


void main() {
	Teacher t1((char*)"rose", 30);
	Teacher t2 = t1;
	t2.myprint();
	getchar();
}

输出

有参构造函数
拷贝构造函数
rose,30
  • 浅拷贝有可能会出现第二次释放变量导致出现异常的情况

例如:出现异常的情况

using namespace std;
class Teacher {
private:
	char* name;
	int age;
public:
		//有参构造函数
	Teacher(char *name, int age) {
		int len = strlen(obj.name);
		this->name = (char*)malloc(len+1);
		strcpy(this->name,name);
		this->age = age;
		cout << "有参构造函数" << endl;
	}
	//析构函数
	~Teacher() {
		cout << "析构函数" << endl;
		free(this->name);
	}

    

	void myprint() {
		cout << name << "," << age << endl;
	}
};

void func(){
    Teacher t1((char*)"rose", 30);
	Teacher t2 = t1;
	t2.myprint();
} 

void main() {
    func();
	getchar();
}

3.2 深拷贝

深拷贝拷贝的是指针指向的数据内容(两块内存区域)

using namespace std;
class Teacher {
private:
	char* name;
	int age;
public:
		//有参构造函数
	Teacher(char *name, int age) {
	    int len = strlen(obj.name);
		this->name = (char*)malloc(len+1);
		strcpy(this->name,name);
		this->age = age;
		cout << "有参构造函数" << endl;
	}
	//析构函数
	~Teacher() {
		cout << "析构函数" << endl;
		free(this->name);
	}

	//拷贝构造函数(深拷贝)
	Teacher(const Teacher &obj) {
	    //复制name属性
	    int len = strlen(obj.name);
		this->name = (char*)malloc(len+1);
		strcpy(this->name,obj.name);
		this->age = obj.age;
		cout << "拷贝构造函数" << endl;
	}

	void myprint() {
		cout << name << "," << age << endl;
	}
};

void func(){
    Teacher t1((char*)"rose", 30);
    //声明时会被调用
	Teacher t2 = t1;
	//下面这种方式不会被调用
	//Teacher t1;
	//Teacher t2;
	//t1 = t2;
	t2.myprint();
}

void main() {
	func();
	getchar();
}

3.3 拷贝构造函数被被调用的场景

  1. 声明时赋值
  2. 作为参数传入,实参给形参赋值
  3. 作为函数返回值返回,给变量初始化赋值

4、构造函数属性初始化列表

构造函数属性初始化列表的格式为:

[构造函数名称]([本类中属性列表],[第一个类对象的属性列表],[第二个类对象的属性列表]):[第一个类对象]([第一个类对象的属性列表]),[第二个类对象]([第二个类对象的属性列表]){
    
}

示例如下:

class Teacher{
private:
    char* name;
public:
    Teacher(char* name){
        this->name = name;
        cout << "Teacher有参构造函数" << endl;
    }
    ~Teacher(){
        cout << "Teacher析构函数" << endl;
    }
    char* getName(){
        return this->name;
    }
};

class Student{
private:
    int id;
    Teacher t1;
public:
    Student(int id,char* t1_name) : t1(t1_name){
        this->id = id;    
        cout << "Student有参构造函数" << endl;
    }
    ~Student(){
        cout << "Student析构函数" << endl;
    }
    void myprint(){
        cout << this->id << "同学的老师是" << t1.getName() << endl;
    }
};

void func(){
    Student t1(16,(char*)"Jack");
    t1.myprint();
}

void main(){
    func();
    
    getchar();
}

三、C++中的new 和 delete的使用

C++中通过new和delete来进行动态内存分配,new 和delete成对出现
C++中在使用new和delete会对应调用构造函数和析构参数,通过C中的malloc方式则不会调用构造函数和析构函数

class Teacher{
private:
    char* name;
public:
    Teacher(char* name){
        this->name = name;
        cout << "Teacher有参构造函数" << endl;
    }
    ~Teacher(){
        cout << "Teacher析构函数" << endl;
    }
    void setName(char* name){
        this->name = name;
    }
    char* getName(){
        return this->name;
    }
};

void func(){
    //初始化,返回指针地址
    Teacher *t1 = new Teacher((char*)"Jack");
    //使用
    //释放
    delete t1;
    int *p2 = new int[10];
    p2[0] = 11;
    //释放数组
    delete p2;
}

void main(){
    func();
    
    getchar();
}