C++面向对象-类的基本使用方法

文章目录

  • 什么是面向过程
    • 面向对象编程,最重要的第一个概念:类
    • 什么是对象?
    • 对象的基本使用
    • 默认构造函数
    • 手动定义的默认构造函数
    • 自定义的重载构造函数
    • 拷贝构造函数
    • 什么时候调用拷贝构造函数
    • 合成的拷贝构造函数
    • 赋值构造函数
    • 析构函数

什么是面向过程

什么是面向过程?
根据程序的执行过程,来设计软件的所有细节。

面向过程的缺点:
开发大型项目时,越来越难以把控,甚至失去控制。
后期维护、更新成本很大。

解决方案:
使用面向对象。

面向过程是C语言的东西,C++是面向对象

什么是面向对象?
面向对象是一种开发思想,一种全新的开发方式。
面向对象思想的重要性:
开发大型项目必备,是高级程序员的必备技能!

面向对象编程,最重要的第一个概念:类

“人类”是一个抽象的概念,不是具体的某个人。
“类”,是看不见,摸不着的,是一个纯粹的概念.
“类”,是一种特殊的“数据类型”,不是一个具体的数据。

注意:类, 和基本数据类型(char/int/short/long/long long/float/double)不同

什么是对象?

对象,是一个特定“类”的具体实例。

对象和普通变量有什么区别?
一般地,一个对象,就是一个特殊的变量,但是有跟丰富的功能和用法。

类的构成:方法和数据
C++面向对象-类的基本使用方法_第1张图片
C++面向对象-类的基本使用方法_第2张图片

对象的基本使用

这里我们用类来创建一个小萝莉


```cpp
#include 
#include 
#include 

using namespace std;


class Lolita{
public://公有的,对外的
	void introduction();
	void hobby();

	string getName();
	int getage();
	int getstature();

private://私有的
	string name;
	int age;
	int Stature;
};//注意这里要带分号

void Lolita::introduction(){
	cout<<"你好,我是一名小萝莉!"<<endl;
}

void Lolita::hobby(){
	cout<<"我的兴趣爱好是:吃喝玩乐!"<<endl;
}

string Lolita::getName(){
	return name;
}

int Lolita::getage(){
	return age;
}

int Lolita::getstature(){
	return Stature;
}


int main(void){
	Lolita Bite;
	Bite.introduction();
	Bite.hobby();

	system("pause");
	return 0;
}

上面是类最基本的用法

默认构造函数

没有参数的构造函数,称为默认构造函数。
1.合成的默认构造函数
但没有手动定义默认构造函数时,编译器自动为这个类定义一个构造函数。
1)如果数据成员使用了“类内初始值”,就使用这个值来初始化数据成员。【C++11】
2)否则,就使用默认初始化(实际上,不做任何初始化)

就好比下面这段代码,我调用上面这个萝莉的年龄age使用的就是默认构造函数

#include 
#include 
#include 

using namespace std;


class Lolita{
public://公有的,对外的
	void introduction();
	void hobby();

	string getName();
	int getage();
	int getstature();

private://私有的
	string name;
	int age;
	int Stature;
};//注意这里要带分号

void Lolita::introduction(){
	cout<<"你好,我是一名小萝莉!"<<endl;
}

void Lolita::hobby(){
	cout<<"我的兴趣爱好是:吃喝玩乐!"<<endl;
}

string Lolita::getName(){
	return name;
}

int Lolita::getage(){
	return age;
}

int Lolita::getstature(){
	return Stature;
}


int main(void){
	Lolita Bite;
	Bite.introduction();
	Bite.hobby();
	cout<<"萝莉的年龄是:"<<Bite.getage()<<endl;

	system("pause");
	return 0;
}

C++面向对象-类的基本使用方法_第3张图片
注意:
只要手动定义了任何一个构造函数,编译器就不会生成“合成的默认构造函数”
一般情况下,都应该定义自己的构造函数,不要使用“合成的默认构造函数”
【仅当数据成员全部使用了“类内初始值”,才宜使用“合成的默认构造函数”】
类内初始值就是在创建数据的时候已经初始化好了

手动定义的默认构造函数

#include 
#include 
#include 

using namespace std;


class Lolita{
public://公有的,对外的
	void introduction();
	void hobby();
	Lolita();//手动定义的“默认构造函数”

	string getName();
	int getage();
	float getstature();

private://私有的
	string name;
	int age;
	float Stature;
};//注意这里要带分号

void Lolita::introduction(){
	cout<<"你好,我是一名小萝莉!"<<endl;
}

void Lolita::hobby(){
	cout<<"我的兴趣爱好是:吃喝玩乐!"<<endl;
}

string Lolita::getName(){
	return name;
}

int Lolita::getage(){
	return age;
}

float Lolita::getstature(){
	return Stature;
}

Lolita::Lolita(){
	name="咬米";
	age=18;
	Stature=1.6;
}

int main(void){
	Lolita Bite;
	Bite.introduction();
	Bite.hobby();

	cout<<"萝莉的名字是:"<<Bite.getName()<<endl;
	cout<<"萝莉的年龄是:"<<Bite.getage()<<"岁"<<endl;
	cout<<"萝莉的身高是:"<<Bite.getstature()<<"米"<<endl;

	system("pause");
	return 0;
}

C++面向对象-类的基本使用方法_第4张图片
说明:如果某数据成员使用类内初始值,同时又在构造函数中进行了初始化,
那么以构造函数中的初始化为准。
相当于构造函数中的初始化,会覆盖对应的类内初始值。

自定义的重载构造函数

简单的说就是,自己可以在创建对象的时候自己根据需求自定义里面的值

#include 
#include 
#include 

using namespace std;


class Lolita{
public://公有的,对外的
	void introduction();
	void hobby();
	Lolita();//手动定义的“默认构造函数”.
	Lolita(string x,int y,float j);//自定义构造函数

	string getName();
	int getage();
	float getstature();

private://私有的
	string name;
	int age;
	float Stature;
};//注意这里要带分号

void Lolita::introduction(){
	cout<<"你好,我是一名小萝莉!"<<endl;
}

void Lolita::hobby(){
	cout<<"我的兴趣爱好是:吃喝玩乐!"<<endl;
}

string Lolita::getName(){
	return name;
}

int Lolita::getage(){
	return age;
}

float Lolita::getstature(){
	return Stature;
}

Lolita::Lolita(){
	name="咬米";
	age=18;
	Stature=1.6;
}
//自定义构造函数
Lolita::Lolita(string x,int y,float j){
	this->name=x;
	this->age=y;
	this->Stature=j;
}

int main(void){
	Lolita Bite;
	Bite.introduction();
	Bite.hobby();
	cout<<"萝莉的名字是:"<<Bite.getName()<<endl;
	cout<<"萝莉的年龄是:"<<Bite.getage()<<"岁"<<endl;
	cout<<"萝莉的身高是:"<<Bite.getstature()<<"米"<<endl;

	cout<<"----华丽的分割线----"<<endl;

	Lolita tmp("小米",20,1.65);
	cout<<"萝莉的名字是:"<<tmp.getName()<<endl;
	cout<<"萝莉的年龄是:"<<tmp.getage()<<"岁"<<endl;
	cout<<"萝莉的身高是:"<<tmp.getstature()<<"米"<<endl;

	system("pause");
	return 0;
}

C++面向对象-类的基本使用方法_第5张图片

拷贝构造函数

1.手动定义的拷贝构造函数
在下面的代码中,我把打印输出信息封装成了prin函数,太懒了,懒得一个个打印输出

什么时候调用拷贝构造函数

1.调用函数时,实参是对象,形参不是引用类型
如果函数的形参是引用类型,就不会调用拷贝构造函数
2.函数的返回类型是类,而且不是引用类型
3.对象数组的初始化列表中,使用对象。

#include 
#include 
#include 

using namespace std;


class Lolita{
public://公有的,对外的
	void introduction();
	void hobby();
	void prin();

	Lolita();//手动定义的“默认构造函数”.
	Lolita(string x,int y,float j);//自定义构造函数
	Lolita(const Lolita&man);//手动定义的拷贝构造函数

	string getName();
	int getage();
	float getstature();

private://私有的
	string name;
	int age;
	float Stature;
};//注意这里要带分号

void Lolita::introduction(){
	cout<<"你好,我是一名小萝莉!"<<endl;
}

void Lolita::hobby(){
	cout<<"我的兴趣爱好是:吃喝玩乐!"<<endl;
}

void Lolita::prin(){
	introduction();
	hobby();
	cout<<"我的名字是:"<<name<<endl;
	cout<<"我的年龄是:"<<age<<"岁"<<endl;
	cout<<"我的身高是:"<<Stature<<"米"<<endl;
}

string Lolita::getName(){
	return name;
}

int Lolita::getage(){
	return age;
}

float Lolita::getstature(){
	return Stature;
}

Lolita::Lolita(){
	name="咬米";
	age=18;
	Stature=1.6;
}
//自定义构造函数
Lolita::Lolita(string x,int y,float j){
	this->name=x;
	this->age=y;
	this->Stature=j;
}
//使用自定义的拷贝构造函数
Lolita::Lolita(const Lolita&man){
	name=man.name;
	age=man.age;
	Stature=man.Stature;
}

int main(void){
	Lolita Bite1("蔡萝莉",20,1.63);
	Lolita Bite2(Bite1);
	Bite1.prin();
	cout<<"----华丽的分割线----"<<endl;
	Bite2.prin();

	system("pause");
	return 0;
}

C++面向对象-类的基本使用方法_第6张图片

合成的拷贝构造函数

合成拷贝构造函数就是什么都不做,直接赋值,但是这样称为浅拷贝,遇到指针什么的就完犊子了,因为指针指的是地址
不定义拷贝构造函数,编译器会生成“合成的拷贝构造函数”
解决办法就是使用深拷贝,就是自己写一个,如果有指针类型的值,就用new开创一块新内存

#include 
#include 
#include 
#include 

using namespace std;

// 定义一个“人类”
class Human {
public:
	Human();
	Human(int age, int salary);
	Human(const Human&);  //不定义拷贝构造函数,编译器会生成“合成的拷贝构造函数”

	void eat();
	void sleep();
	void play();
	void work();

	string getName();
	int getAge();
	int getSalary();
	void setAddr(const char *newAddr);
	const char* getAddr();

private:
	string name = "Unknown";
	int age = 28;
	int salary;
	char *addr;
};

Human::Human() {
	name = "无名氏";
	age = 18;
	salary = 30000;
}

Human::Human(int age, int salary) {
	cout << "调用自定义的构造函数" << endl;
	this->age = age;      //this是一个特殊的指针,指向这个对象本身
	this->salary = salary;
	name = "无名";

	addr = new char[64];
	strcpy_s(addr, 64, "China");
}

Human::Human(const Human &man) {
	cout << "调用自定义的拷贝构造函数" << endl;
	age = man.age;      //this是一个特殊的指针,指向这个对象本身
	salary = man.salary;
	name = man.name;
	// 深度拷贝
	addr = new char[64];
	strcpy_s(addr, 64, man.addr);
}

void Human::eat() {
	cout << "吃炸鸡,喝啤酒!" << endl;
}

void Human::sleep() {
	cout << "我正在睡觉!" << endl;
}

void Human::play() {
	cout << "我在唱歌! " << endl;
}

void Human::work() {
	cout << "我在工作..." << endl;
}

string Human::getName() {
	return name;
}

int Human::getAge() {
	return age;
}

int Human::getSalary() {
	return salary;
}

void Human::setAddr(const char *newAddr) {
	if (!newAddr) {
		return;
	}

	strcpy_s(addr, 64, newAddr);
}

const char* Human::getAddr() {
	return addr;
}

int main(void) {
	Human  h1(25, 35000);  // 使用自定义的默认构造函数
	Human  h2(h1);  // 使用自定义的拷贝构造函数

	cout << "h1 addr:" << h1.getAddr() << endl;
	cout << "h2 addr:" << h2.getAddr() << endl;

	h1.setAddr("长沙");

	cout << "h1 addr:" << h1.getAddr() << endl;
	cout << "h2 addr:" << h2.getAddr() << endl;

	system("pause");
	return 0;
}

赋值构造函数

#include 
#include 
#include 

using namespace std;


class Lolita{
public://公有的,对外的
	void introduction();
	void hobby();
	void prin();

	Lolita();//手动定义的“默认构造函数”.
	Lolita(string x,int y,float j);//自定义构造函数
	Lolita(const Lolita&man);//手动定义的拷贝构造函数
	Lolita& operator=(const Lolita&);//赋值构造函数

	string getName();
	int getage();
	float getstature();

private://私有的
	string name;
	int age;
	float Stature;
};//注意这里要带分号

void Lolita::introduction(){
	cout<<"你好,我是一名小萝莉!"<<endl;
}

void Lolita::hobby(){
	cout<<"我的兴趣爱好是:吃喝玩乐!"<<endl;
}

void Lolita::prin(){
	introduction();
	hobby();
	cout<<"我的名字是:"<<name<<endl;
	cout<<"我的年龄是:"<<age<<"岁"<<endl;
	cout<<"我的身高是:"<<Stature<<"米"<<endl;
}

string Lolita::getName(){
	return name;
}

int Lolita::getage(){
	return age;
}

float Lolita::getstature(){
	return Stature;
}

Lolita::Lolita(){
	name="咬米";
	age=18;
	Stature=1.6;
}
//自定义构造函数

Lolita::Lolita(string x,int y,float j){
	this->name=x;
	this->age=y;
	this->Stature=j;
}
//使用自定义的拷贝构造函数
Lolita::Lolita(const Lolita&man){
	name=man.name;
	age=man.age;
	Stature=man.Stature;
}
//赋值构造函数
Lolita& Lolita::operator=(const Lolita &man){
	if(this==&man){
		return *this;//坚持是不是对自己赋值比如:Bite1=Bite1
	}
	name=man.name;
	age=man.age;
	Stature=man.Stature;

	return *this;
}
int main(void){
	Lolita Bite1("蔡萝莉",20,1.63);
	Lolita Bite2;
	//Lolita Bite2(Bite1);//这样使用的是拷贝函数
	Bite2=Bite1;//这样使用的才是赋值构造函数
	Bite1.prin();
	cout<<"----华丽的分割线----"<<endl;
	Bite2.prin();

	system("pause");
	return 0;
}

C++面向对象-类的基本使用方法_第7张图片
如果没有定义赋值构造函数,编译器会自动定义“合成的赋值构造函数”,
与其他合成的构造函数,是“浅拷贝”(又称为“位拷贝”)。

析构函数

作用:
对象销毁前,做清理工作。

具体的清理工作,一般和构造函数对应
比如:如果在构造函数中,使用new分配了内存,就需在析构函数中用delete释放。

如果构造函数中没有申请资源(主要是内存资源),
那么很少使用析构函数。

函数名:
~类型
没有返回值,没有参数,最多只能有一个析构函数

访问权限:
一般都使用public

使用方法:
不能主动调用。
对象销毁时,自动调用。
如果不定义,编译器会自动生成一个析构函数(什么也不做)在这里插入代码片

#include 
#include 
#include 
#include 

using namespace std;

// 定义一个“人类”
class Human {
public:
	Human();
	Human(int age, int salary);
	Human(const Human&);  //不定义拷贝构造函数,编译器会生成“合成的拷贝构造函数”
	Human& operator=(const Human &);
	~Human(); //析构函数
     ......

private:
	string name = "Unknown";
	int age = 28;
	int salary;
	char *addr;
};

Human::Human() {
	name = "无名氏";
	age = 18;
	salary = 30000;

	addr = new char[64];
	strcpy_s(addr, 64, "China");
	cout << "调用默认构造函数-" << this << endl;
}

......

Human::~Human() {
	cout << "调用析构函数-" << this  << endl;  //用于打印测试信息
	delete addr;
}

void test() {
	Human h1;

	{
		Human h2;
	}
	cout << "test()结束" << endl;
}

int main(void) {
	test();

	system("pause");
	return 0;
}

如果对你有用请点赞,谢谢!

C++面向对象-类的基本使用方法_第8张图片

你可能感兴趣的:(笔记,c++,c++)