C++学习笔记2——封装篇(上)

学习教程:https://www.imooc.com/learn/382

  1. 从栈实例化对象
//定义:
class TV
{
	public:
		char name[20];
		int type;

		void changeVol();
		void power();
};

int main()
{
	//调用:
	TV tv;
	YV tv[20];

	//访问:
	tv.type = 0;
	tv.changeVol();
	return 0;
}

  1. 从堆实例化对象
//定义:
class TV
{
	public:
		char name[20];
		int type;

		void changeVol();
		void power();
};


int main()
{
	//调用:
	TV*p = new TV();
	TV*q = new TV[20];
	//todo
	//访问:
	p->type = 0;
	p->changeVol();
	//释放:
	delete p;
	delete []q;
	return 0;
}

综合举例:

#include <iostream>
using namespace std;

class Coordinate
{
	public:
		int x;
		int y;
		void printx()
		{
			cout << x << endl;
		}
		void printy()
		{
			cout << y << endl;
		}
 };
 
 int main()
 {
 	//栈:
	 //定义:
	  Coordinate coor;
	 //调用: 
	  coor.x = 10;
	  coor.y = 20;
	  coor.printx();
	  coor.printy();
	//堆:
	 //定义:
	 Coordinate *co = new Coordinate();
	 if (co == NULL)
	 {
	 	//申请空间失败
		 return 0; 
	 }
	 //调用: 
	 co->x = 100;
	 co->y = 200;
	 co->printx();
	 co->printy(); 
	 //释放(堆的):
	 delete co;
	 co = NULL;
	 
	 return 0;
	  
 }
  1. string

头文件: #include <string>
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
举例使用:

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

int main()
{

		string name;
		cout << "input name:" << endl;
		getline(cin, name);
		if (name.empty()) //用到了string的empty()
		{
			cout << "null" << endl;
			return 0;
		}
		if (name == "imooc") //用到了string的判定相等 
		{
			cout << "is imooc" << endl;
		}
		cout << "hello" + name << endl; //字符串+string
		cout << "length:" << name.size() << endl; //用到了string的size()
		cout << "first letter:" << name[0] << endl; //用到了string的返回字符个数
		return 0;
	
}
  1. 封装
    在这里插入图片描述
    左图是普通的封装,右图是有限定的封装(满足条件才赋值)
    右图更方便,例:给age赋1000,显然不合理,按右图,不满足条件,就不会赋值了,省事
    在这里插入图片描述
    图中,m_iWheelCount指轮子的个数,这里只希望被读,不希望被改变

举例:

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

class Student
{
public:
	void setName(string name)
	{
		strName = name;
	}
	string getName()
	{
		return strName;
	}
	void setGender(string gender)
	{
		strGender = gender;
	}
	string getGender()
	{
		return strGender;
	}
	int getScore()
	{
		return iScore;
	}
	void initScore() //初始化
	{
		iScore = 0;
	}
	void study(int score)
	{
		iScore += score;
	}
private:
	string strName;
	string strGender;
	int iScore;
};

int main()
{
	Student stu;
	stu.setName("zhangsan");
	stu.setGender("男");
	stu.initScore();
	stu.study(3);
	stu.study(2);

	cout << stu.getName() << "  " << stu.getGender() << "  " << stu.getScore() << endl;

	return 0;
	
}

类外定义

在这里插入图片描述
在这里插入图片描述
类内定义的成员函数,编译器会将其优先编译为类内函数。不会将“inline”写出来,但会以“inline”的方式优先编译,对复杂的成员函数,无法编译成内联函数的,再编译成普通的函数

类外定义:指成员函数的函数体写在类的外面
在这里插入图片描述
同文件类外定义:指成员函数虽然定义在类的外面,但其定义与类的定义在同一个文件中
在这里插入图片描述
分文件类外定义(常用):
在这里插入图片描述
同文件类外定义举例:

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

class Teacher
{
	public:
		void setName(string _name);
		string getName();
		void setGender(string _gender);
		string getGender();
		void setAge(int _age);
		int getAge();
		void teach();
	private:
		string strName;
		string strGender;
		int iAge;
}; 

void Teacher::setName(string _name)
{
	strName = _name;
}
string Teacher::getName()
{
	return strName;
}
void Teacher::setGender(string _gender)
{
	strGender = _gender;
}
string Teacher::getGender()
{
	return strGender;
}
void Teacher::setAge(int _age)
{
	iAge = _age;
}
int Teacher::getAge()
{
	return iAge;
}
void Teacher::teach()
{
	cout << "上课" << endl;
}

int main()
{
	Teacher t;
	t.setName("zhangsan");
	t.setGender("男");
	t.setAge(30);
	cout << t.getName() << "  " << t.getGender() << "  " << t.getAge() << "  " <<endl;
	t.teach();
	return 0; 
}

以上例子改为分文件类外定义:
把class 定义放到Teacher.h文件(自己新建,记得加上头文件)
set get等方法实体还是留到在Teach.cpp文件(即上述例子的文件)
cpp文件加一句#include "Teacher.h"

对象结构

在这里插入图片描述
栈区:内存由系统来进行操作,无论是分配还是回收,都不需要程序员关心
堆区:由程序员管理,分配用new,回收用delete

在这里插入图片描述
定义时不占内存,实例化为car1、car2、car3后,每个对象都会在栈上开辟一段内存,用来存储各自的数据,逻辑代码放在代码区,谁需要谁就去调用,找到相应的代码入口,就可以执行相应的代码程序

对象初始化

在这里插入图片描述

构造函数

将初始化的代码写在构造函数内,就能初始化数据。
构造函数在实例化对象时,调用且仅被调用一次。
构造函数与类同名
构造函数没有返回值
构造函数可以有多个重载形式,重载的时候要遵循重载函数的规则
实例化对象时,即使有多个构造函数,使用的时候也只用到一个构造函数
当用户没有定义构造函数时,编译器自动生成一个构造函数

无参构造函数:
在这里插入图片描述
有参构造函数:
在这里插入图片描述
重载构造函数:
在这里插入图片描述
综合举例:
用VS,在同一个项目下

Teacher.h文件:

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

class Teacher
{
public:
	Teacher(); //无参构造函数 
	Teacher(string name, int age = 10); //有参构造函数 ,这里给年龄设了默认值,如果后面没有给年龄赋值,就用默认值 
	//如果全部都设默认值,那 Teacher() 就不知道是调用无参构造函数还是调用有参且使用默认值。 
	void setName(string _name);
	string getName();
	void setAge(int _age);
	int getAge();

private:
	string strName;
	int iAge;
};

Teacher.cpp文件

#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;

Teacher::Teacher()
{
	strName = "zhang";
	iAge = 35;
	cout << "Teacher()" << endl;
}

Teacher::Teacher(string name, int age)
{
	strName = name;
	iAge = age;
	cout << "Teacher(string name,int age)" << endl;
}

void Teacher::setName(string _name)
{
	strName = _name;
}
string Teacher::getName()
{
	return strName;
}
void Teacher::setAge(int _age)
{
	iAge = _age;
}
int Teacher::getAge()
{
	return iAge;
}

demo.cpp文件:

#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;

int main()
{
	Teacher t1; //调用无参构造函数 
	Teacher t2("Li", 23); //调用有参构造函数
	Teacher t3("wang"); //调用有参构造函数,但不给年龄赋值,此时会用默认值 => 说明构造函数除了重载,还可以给参数赋默认值 

	//检查是否 用内存存了数据 
	cout << t1.getName() << "  " << t1.getAge() << endl;
	cout << t2.getName() << "  " << t2.getAge() << endl;
	cout << t3.getName() << "  " << t3.getAge() << endl;
	return 0;
}

运行demo.cpp文件

默认构造函数

int main()
{
	Student stu1(); //从栈中实例化对象
	Student *p = NULL;
	p = new Student(); //从堆中实例化对象,并用指针指向他
	return 0;
}

两种实例化对象的方法,调用的构造函数都不用传参数,对于这样的调用形式,在定义构造函数时,可以有不同方式

class Student
{
	public:
		Student(){} //这样定义,构造函数本身就没有参数
		Student(string name = "zhang") 
	private:
		string strName;

以上两种定义方式,在实例化Student对象时,都不用给构造函数传递形参

默认构造函数:在实例化对象时,不需要传递参数的构造函数

以上两个都是默认构造函数

构造函数初始化列表:
在这里插入图片描述
红色句子为初始化列表
格式:
构造函数后加 : 多个成员用 , 隔开
赋值用()不用=

初始化列表特性:
初始化列表先于构造函数执行
初始化列表只能用于构造函数
初始化列表可以同时初始化多个数据成员

举例说明初始化列表存在的必要性:

class Circle
{
	public:
		Circle(){dPi = 3.14} //因为dPi是const修饰的常量,不可以被赋值,此句会引起报错,是错的
		Circle():dPi(3.14) {} //用初始化列表赋初值,是对的
	private:
		const double dPi; // pI是不变的数,设为const修饰的常量

举例示范:
用VS,同一个项目下:
Teacher.h

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

class Teacher
{
	public:
		Teacher(string name = "zhang" , int age = 10 , int m = 100); //默认构造函数 
		void setName(string _name);
		string getName();
		void setAge(int _age);
		int getAge();
		int getMax();

	private:
		string strName;
		int iAge;
		const int iMax; //学生最大数量
};

Teacher.cpp

#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;

Teacher::Teacher(string _name , int _age,int m):strName(_name),iAge(_age),iMax(m)
{
	//iMax = m; //iMax是const修饰的常量,如果在这里初始化,会报错
	cout << "Teacher(string _name , int _age)" << endl; //体现函数被调用
}

int Teacher::getMax()
{
	return iMax;
}

void Teacher::setName(string _name)
{
	strName = _name;
}
string Teacher::getName()
{
	return strName;
}
void Teacher::setAge(int _age)
{
	iAge = _age;
}
int Teacher::getAge()
{
	return iAge;
}

demo.cpp

#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;

int main()
{
	Teacher t1;  //有默认构造函数,如此语句这样定义,则输出的都是默认值,其中max是const修饰的常量
	cout << t1.getName() << "  " << t1.getAge() << "  " << t1.getMax() << endl;
	Teacher t2("wang", 22,150);
	cout << t2.getName() << "  " << t2.getAge() << endl;
	return 0;
}

当构造函数没有参数时,也叫作默认构造函数

“一个类至少有一个默认构造函数”(X)
在申明类时可以不写构造函数,这样这个类就没有默认构造函数了,只是在编译的时候会自动帮我们生成一个构造函数。

当构造函数有参数,但每个参数都有默认值时,也成为默认构造函数

当实例化对象时,如果不使用任何参数,则调用的是默认构造函数

举例:

//定义:
class Student
{
	public:
		Student() //默认构造函数
		{
			cout <<"Student" ;
		}
	private:
		string strName;
};

//实现:
int main()
{
	Student stu1;
	Student stu2 = stu1; //使stu2在实例化的过程中拥有了stu1的值
	Student stu3(stu1); //使stu3在实例化的过程中拥有了stu1的值

	return 0;
}

以上代码的结果,仅输出一行Student
实例化了三个对象,之前说过,实例化对象一定会调用构造函数。后两个对象调用的是 拷贝构造函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
无参构造函数就是默认构造函数。
有参构造函数,如果所有参数都带默认值,那么就是默认构造函数

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值