赞
踩
什么是面向过程?
根据程序的执行过程,来设计软件的所有细节。
面向过程的缺点:
开发大型项目时,越来越难以把控,甚至失去控制。
后期维护、更新成本很大。
解决方案:
使用面向对象。
面向过程是C语言的东西,C++是面向对象
什么是面向对象?
面向对象是一种开发思想,一种全新的开发方式。
面向对象思想的重要性:
开发大型项目必备,是高级程序员的必备技能!
“人类”是一个抽象的概念,不是具体的某个人。
“类”,是看不见,摸不着的,是一个纯粹的概念.
“类”,是一种特殊的“数据类型”,不是一个具体的数据。
注意:类, 和基本数据类型(char/int/short/long/long long/float/double)不同
对象,是一个特定“类”的具体实例。
对象和普通变量有什么区别?
一般地,一个对象,就是一个特殊的变量,但是有跟丰富的功能和用法。
类的构成:方法和数据
这里我们用类来创建一个小萝莉
```cpp #include <iostream> #include <windows.h> #include <string> 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 <iostream> #include <windows.h> #include <string> 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 <iostream> #include <windows.h> #include <string> 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 <iostream> #include <windows.h> #include <string> 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 <iostream> #include <windows.h> #include <string> 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 <iostream> #include <Windows.h> #include <string> #include <string.h> 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 <iostream> #include <windows.h> #include <string> 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 <iostream> #include <Windows.h> #include <string> #include <string.h> 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; }
如果对你有用请点赞,谢谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。