c++基础之封装上
来源:互联网 发布:淘宝身份证认证照片 编辑:程序博客网 时间:2024/06/06 00:41
类的三大特性:封装,继承和多态
一、类和对象的定义
#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 c1; c1.x=1; c1.y=2; c1.printX(); c1.printY(); Coordinate *p=new Coordinate(); p->x=3; p->y=4; p->printX(); p->printY(); delete p; return 0;}
运行结果:
1
2
3
4
二、类的封装
1.面向对象的指导思想
封装是面向对象的三大特征之一,就是将类的状态信息隐藏在类的内部,不允许外部程序直接访问,而通过该类提供的方法来实现对隐藏信息的操作和访问。在代码层次上就是将所有的数据操作转化为对成员函数的调用,即对象在程序的所有行为都通过成员函数来完成。
2.封装的好处
(1)让使用者只能通过程序规定的方法来访问数据;可以方便的加入存取控制语句,限制不合理操作;
(2)隐藏类的实现细节
(3)便于维护,增强了代码的可维护性
(4)例子:
#include <iostream>using namespace std;class Student{public: void setAge(int _age) { if(_age>0&&_age<100) age=_age; else age=0; } int getAge() { return age; } void setName(string _name) { name=_name; } string getName() { return name; }private: string name; int age;};int main(){ Student s1; s1.setAge(10); s1.setName("zhangsan"); cout<<s1.getAge()<<" "<<s1.getName()<<endl; return 0;}
3.类外定义
即成员函数的声明和实现是分开的。
(1)同文件类外定义
#include <iostream>using namespace std;class Student{public: Student();//无参构造函数 Student(string _name,int _age); void setAge(int _age); int getAge(); void setName(string _name); string getName();private: string name; int age;};Student::Student(){}Student::Student(string _name,int _age){}void Student::setAge(int _age){}int Student::getAge(){}void Student::setName(string _name){}string Student::getName(){}int main(){ // ...... return 0;}
(2)不同文件类外定义
♦声明在.h文件中;
#include <iostream>using namespace std;class Student{public: Student();//无参构造函数 Student(string _name,int _age); void setAge(int _age); int getAge(); void setName(string _name); string getName();private: string name; int age;};
♦实现在.cpp文件中。
#include "Studnet.h"Student::Student(){}Student::Student(string _name,int _age){}void Student::setAge(int _age){}int Student::getAge(){}void Student::setName(string _name){}string Student::getName(){}
♦使用在main.cpp中#include "Student.h"#include <iostream>using namespace std;int main(){ // ...... return 0;}
三、对象的结构1.内存按照用途分为5个区
(1)栈区:内存由系统分配和回收,程序员无需关心。
int x=0;int *p=NULL:
(2)堆区:分配内存由new分配,释放由delete释放。
(3)全局区:存储全局变量和静态变量。
(4)常量区:存储字符串和常量。
(5)代码区:存储逻辑代码的二进制
2.对象中数据是如何存储的。
类在实例化之前是不会占用堆或栈的内存的,但在实例化之后,每个对象都会在栈中开辟内存,占据不同的内存。逻辑代码却只有一份,放在代码区。所有的对象共享逻辑代码。
四、对象的初始化
1.初始化函数
class Student{public: void init() { name=""; age=0; } void setAge(int _age); int getAge(); void setName(string _name); string getName();private: string name; int age;};
但是有缺点,比如忘记调用或者重复调用初始化函数,所以产生了构造函数。2.构造函数
(1)分为无参构造函数和有参构造函数
(2)特点
①在对象实例化时自动调用,而且可以重载。
②实例化时只会调用一个构造函数
③当用户没有定义构造函数时,编译器自动生成一个构造函数。
(3)例子
#include <iostream>using namespace std;class Student{public: Student()//无参构造函数 { name="li"; age=0; } Student(string _name,int _age)//有参构造函数 { name=_name; age=_age; } void setAge(int _age) { if(_age>0&&_age<100) age=_age; else age=0; } int getAge() { return age; } void setName(string _name) { name=_name; } string getName() { return name; }private: string name; int age;};int main(){ Student s1; Student s2("zhang",10); cout<<s1.getName()<<" "<<s1.getAge()<<endl; cout<<s2.getName()<<" "<<s2.getAge()<<endl; return 0;}
运行结果:
3.构造函数初始化列表
(1)例子
#include <iostream>using namespace std;class Student{public: Student():name("li"),age(0){}; Student(string _name,int _age):name(_name),age(_age){}; void setAge(int _age) { if(_age>0&&_age<100) age=_age; else age=0; } int getAge() { return age; } void setName(string _name) { name=_name; } string getName() { return name; }private: string name; int age;};int main(){ Student s1; Student s2("zhang",10); cout<<s1.getName()<<" "<<s1.getAge()<<endl; cout<<s2.getName()<<" "<<s2.getAge()<<endl; return 0;}
(2)特点①初始化列表先于构造函数执行,编译器先给初始化列表的数据成员赋值,再执行构造函数中的代码
②初始化列表只能用于构造函数
③效率高且速度快
(3)初始化列表的必要性(不可取代的地位)
♦错误的代码:
class Circle{ public: Circle() { PI=3.14; } private: const double PI;};
♦正确的代码class Circle{ public: Circle():PI(3.14){} private: const double PI;};
五、拷贝构造函数
1.浅拷贝
只是将数据成员的值进行copy
#include<iostream>using namespace std;class Array{public: Array() { m_iCount=5; arr=new int[m_iCount]; cout<<"Array()"<<endl; } Array(const Array& a1) { cout<<"Array&"<<endl; m_iCount=a1.m_iCount; arr=a1.arr; } ~Array() { m_iCount=0; delete []arr; cout<<"~Array()"<<endl; } void printAddr() { cout<<arr<<endl; }private: int m_iCount; int *arr;};int main(){ Array a1; Array a2=a1; a1.printAddr(); a2.printAddr(); return 0;}
运行结果:运行结果:
地址指向相同的内存。
存在问题:
♦两个对象的arr指向的是同一块地址,如果对a2的arr重新赋值,则a1的arr也会变。
♦销毁对象的时候销毁了两次,即同一块内存被释放了两次。
2.深拷贝
copy时不是简单地copy地址,而是将里面的内容copy过来
#include<iostream>using namespace std;class Array{public: Array() { m_iCount=5; arr=new int[m_iCount]; cout<<"Array()"<<endl; } Array(const Array& a1) { cout<<"Array&"<<endl; m_iCount=a1.m_iCount; arr=new int[m_iCount]; for(int i=0;i<m_iCount;i++) arr[i]=a1.arr[i]; } ~Array() { m_iCount=0; delete []arr; cout<<"~Array()"<<endl; } void printAddr() { cout<<arr<<endl; }private: int m_iCount; int *arr;};int main(){ Array a1; Array a2=a1; a1.printAddr(); a2.printAddr(); return 0;}
运行结果:
地址指向不同的内存。
六、析构函数
1.对象销毁时自动调用,回收资源,收拾残局。
如果没有自定义析构函数,系统也会自动生成一个析构函数。
2.例子
#include <iostream>using namespace std;class Student{public : Student() { cout<<"Studnet"<<endl; } ~Student() { cout<<"~Student"<<endl; }private: string name;};int main(){ Student s1; return 0;}
运行结果:
3.析构函数存在的必要
如果定义的是指针,可以销毁堆内存。
#include <iostream>using namespace std;class Student{public : Student() { name=new char[20]; cout<<"Studnet"<<endl; } ~Student() { delete []name; cout<<"~Student"<<endl; }private: char *name;};int main(){ Student s1; return 0;}
运行结果:- c++基础之封装上
- Java基础之--封装
- Java基础之封装
- OOP之封装 【C#】
- OOP之封装 【C#】
- c++基础之封装下
- java 基础复习之封装
- Ajax基础之封装3
- C语言基础 上
- Objective - C基础: 第二天 - 1.封装思想初认识之set和get方法
- 黑马程序员--IOS基础--Objective C学习--面向对象特性之--封装
- Objective-C基础学习笔记(三)-面向对象的三大特性之封装
- C++远征之封装篇上
- c++学习笔记之封装篇(上)
- c++学习笔记之封装篇(上)
- 黑马程序员_java基础之封装
- 1--java基础回顾之封装
- java基础面向对象之封装
- docker介绍和使用
- 欢迎使用CSDN-markdown编辑器
- docker容器博文
- git版本管理工具使用
- map集合操作
- c++基础之封装上
- mongodb-linux配置-使用
- mongodb-多节点复制及的使用
- caffe blob操作
- windows7系统盘满了之后怎么办
- mongodb文档
- mongodb复制集的监控
- 结构体总结
- mongodb复制集的相关操作