什么是面向过程?
根据程序的执行过程,来设计软件的所有细节。
面向过程的缺点:
开发大型项目时,越来越难以把控,甚至失去控制。
后期维护、更新成本很大。
解决方案:
使用面向对象。
面向过程是C语言的东西,C++是面向对象
什么是面向对象?
面向对象是一种开发思想,一种全新的开发方式。
面向对象思想的重要性:
开发大型项目必备,是高级程序员的必备技能!
“人类”是一个抽象的概念,不是具体的某个人。
“类”,是看不见,摸不着的,是一个纯粹的概念.
“类”,是一种特殊的“数据类型”,不是一个具体的数据。
注意:类, 和基本数据类型(char/int/short/long/long long/float/double)不同
对象,是一个特定“类”的具体实例。
对象和普通变量有什么区别?
一般地,一个对象,就是一个特殊的变量,但是有跟丰富的功能和用法。
这里我们用类来创建一个小萝莉
```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;
}
注意:
只要手动定义了任何一个构造函数,编译器就不会生成“合成的默认构造函数”
一般情况下,都应该定义自己的构造函数,不要使用“合成的默认构造函数”
【仅当数据成员全部使用了“类内初始值”,才宜使用“合成的默认构造函数”】
类内初始值就是在创建数据的时候已经初始化好了
#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;
}
说明:如果某数据成员使用类内初始值,同时又在构造函数中进行了初始化,
那么以构造函数中的初始化为准。
相当于构造函数中的初始化,会覆盖对应的类内初始值。
简单的说就是,自己可以在创建对象的时候自己根据需求自定义里面的值
#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;
}
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;
}
合成拷贝构造函数就是什么都不做,直接赋值,但是这样称为浅拷贝,遇到指针什么的就完犊子了,因为指针指的是地址
不定义拷贝构造函数,编译器会生成“合成的拷贝构造函数”
解决办法就是使用深拷贝,就是自己写一个,如果有指针类型的值,就用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;
}
如果没有定义赋值构造函数,编译器会自动定义“合成的赋值构造函数”,
与其他合成的构造函数,是“浅拷贝”(又称为“位拷贝”)。
作用:
对象销毁前,做清理工作。
具体的清理工作,一般和构造函数对应
比如:如果在构造函数中,使用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;
}
如果对你有用请点赞,谢谢!