C++中的类和对象(一)
一,类的概念及封装
1.什么是封装
- 第一层含义:封装是面向对象程序设计最基本的特性。把数据(属性)和函数(方法)合成一个整体,这在计算机世界中是用类和对象实现的。(把属性和方法进行封装)
- 第二层含义:把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类或者对象操作,对不可信的进行信息的隐藏。(对属性和方法进行访问控制)
2.类的访问控制
在C++中可以对类的属性和方法定义访问级别,public修饰的属性和方法,可以在类的内部访问,也可以在类的外部进行访问。private修饰的属性和方法,只能在类的内部进行访问。
3.类的意义
- 类是把属性和方法进行封装,同时对类的属性和方法进行访问控制。
- 类是由我们根据客观事物抽象而成,形成一类事物,然后用类去定义对象,形成这类事物的具体个体。
- 类是一个数据类型,类是抽象的,而对象是一个具体的变量,是占用内存空间的。
4,圆类的抽象和封装
# include<iostream>
using namespace std; /* 抽象一个圆类,并对圆的属性和方法进行封装 */
class Circle
{
private:
double r; /* 圆类的半径属性 */
public:
void setR(double r) /* 设置圆的半径 */
{
this->r = r;
}
double getR() /* 获取圆的半径 */
{
return this->r;
}
};
二,构造函数
1.前言
当我们创建一个对象的时候,常常需要做某些初始化操作,例如属性进行赋初值。为了解决这个问题,C++编译器提供了构造函数来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在创建对象时自动执行。
2.构造函数的定义及调用方式
- 定义:C++类中可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数。构造函数可以有参数列表,但是不能有函数返回值。
- 调用:一般情况下C++编译器会自动调用构造函数,但在一些情况下则需要手工调用构造方法。
3.构造函数的分类
- 无参构造函数:构造函数没有函数参数。
- 有参构造函数:构造函数有函数参数。
- 拷贝构造函数:构造函数的参数为const ClassName &vriable。
4.无参构造函数示例及调用
# include<iostream>
using namespace std; /* 抽象一个圆类,并对圆的属性和方法进行封装 */
class Circle
{
private:
double r; /* 圆类的半径属性 */
public:
Circle() /* 无参构造函数 */
{
cout << "无参构造函数被执行" << endl;
}
void setR(double r) /* 设置圆的半径 */
{
this->r = r;
}
double getR() /* 获取圆的半径 */
{
return this->r;
}
}; int main()
{
/* 无参构造函数的调用方式 */
Circle circle1,circle2;
}
5.有参构造函数示例及调用
# include<iostream>
using namespace std; /* 抽象一个圆类,并对圆的属性和方法进行封装 */
class Circle
{
private:
double r; /* 圆类的半径属性 */
public:
Circle(int a,int b) /* 有参构造函数 */
{
cout << "有参构造函数被调用" << endl;
}
void setR(double r) /* 设置圆的半径 */
{
this->r = r;
}
double getR() /* 获取圆的半径 */
{
return this->r;
}
}; int main()
{
/* 有参构造函数调用方式一 */
Circle circle1(, );
/* 有参构造函数调用方式二:程序员手工直接调用构造方法 */
Circle circle2 = Circle(, );
}
6.拷贝构造函数示例及调用
1.拷贝构造函数的调用方式
- 当用对象1初始化对象2的时候拷贝构造函数被调用。
- 当用对象1括号方式初始化对象2的时候拷贝函数被调用。
- 当用对象(此处是元素而而非指针或引用)做函数参数的时候,实参传递给形参的过程会调用拷贝构造函数。
- 当用对象(此处是元素而而非指针或引用)做函数返回值的时候,若用同一类型来接收该返回值,则会执行拷贝构造函数(此时会涉及到匿名对象的去和留的问题,因为函数的返回对象是个匿名对象)。
2.拷贝构造函数调用方式示例
# include<iostream>
using namespace std; class Location
{
private:
int x;
int y;
public:
Location()
{
cout << "无参构造函数被执行" << endl;
}
Location(int x,int y)
{
this->x = x;
this->y = y;
cout << "有参构造函数被执行" << endl;
}
Location(const Location& location)
{
this->x = location.x;
this->y = location.y;
cout << "拷贝构造函数被执行" << endl;
}
~Location()
{
cout << "x = " << this->x << ",y = " << this->y << "析构函数被执行" << endl;
} }; /* 模拟拷贝构造函数调用方式三 */
void setLocation(Location location)
{
cout << "setLocation()全局函数..." << endl;
} /* 模拟拷贝构造函数调用方式四 */
Location getLocation()
{
cout << "getLocation()全局函数..." << endl;
Location location(, );
return location;
} /* 研究拷贝构造函数的调用 */
int main()
{
/* 拷贝构造函数调用方式一 */
cout << "###############方式一###############" << endl;
Location loc1(, );
Location loc2 = loc1; /* 拷贝构造函数调用方式二 */
cout << "###############方式二###############" << endl;
Location loc3(, );
Location loc4(loc3); /* 拷贝构造函数调用方式三 */
cout << "###############方式三###############" << endl;
Location loc5(, );
setLocation(loc5); /* 拷贝构造函数调用方式四 */
cout << "###############方式四###############" << endl;
/* getLocation()产生匿名对象赋值给loc6后,匿名对象执行析构函数,然后对象销毁 */
Location loc6;
loc6 = getLocation();
/* getLocation()产生匿名对象赋值给loc7,匿名对象被扶正,直接转成新对象 */
Location loc7 = getLocation();
}
7.构造函数小结
- 当类中没有定义任何构造函数的时候,C++编译器默认为我们定义一个无参构造函数,函数体为空。
- 当在类中定义任意构造函数后(包括拷贝构造函数),C++编译器就不会为我们定义默认构造函数,也就是说我们定义了构造函数就必须要使用。
- C++默认提供拷贝构造函数是指向的浅拷贝。只是进行了简单的成员变量的值的复制。
- 拷贝构造函数只有当我们写了以后C++编译器才不会给我提供,如若不写则C++编译器会一直提供默认的拷贝构造函数。
三,析构函数
1.析构函数的定义及调用方式
- 定义:C++类中可以定义一个特殊的成员函数来清理对象和释放我们在对象中分配的内存,这个特殊的方法叫做析构函数。
- 调用:当对象生命周期临近结束时,析构函数由C++编译器自动调用。
2.析构函数的使用
析构通常是在对象生命周期结束之前调用,我们会在此时去释放我们在对象中创建的堆内存,保证程序的合理性。
# define _CRT_SECURE_NO_WARNINGS
# include<iostream> using namespace std; class Student
{
private:
char * name;
int age;
public:
Student(char * name, int age)
{
/* 在构造函数中分配堆内存 */
this->name = (char *)malloc(sizeof(name)+);
/* 初始化成员变量 */
strcpy(this->name, name);
this->age = age;
cout << "构造函数被执行..." << endl;
}
~Student()
{
if (this->name != NULL)
{
/* 在析构函数中释放堆内存 */
free(this->name);
this->name = NULL;
this->age = ;
}
cout << "析构函数被执行..." << endl;
}
void print()
{
cout << this->name << " = " << this->age << endl;
} }; int main()
{
Student stu("王刚", );
stu.print();
return ;
}
四,多个对象的构造函数和析构函数
1.对象初始化列表
当我们有一个类成员,它本身是一个类,而且这个成员只有一个带参数的构造函数,没有默认构造函数,这个时候要对这个类成员进行初始化,就必须调用这个类成员的带参构造函数,这个时候可以在定义成员的时候采用该构造函数初始化对象,但是我们想要动态的初始化,则需要将该成员动态接受外界数据,因此出现了对象初始化列表这个概念。
2.类中成员为const修饰
当我们有个类成员,它被const修饰,那么在初始化的时候可以直接在定义变量的时候初始化,也可以在使用对象初始化列表的时候进行初始化。
3.对象初始化示例
# include<iostream> using namespace std; /* 定义A类 */
class A
{
private:
int a;
int b;
public:
A(int a, int b)
{
this->a = a;
this->b = b;
cout << "A(" << this->a << "," << this->b << ")有参构造函数被执行" << endl;
}
~A()
{
cout << "~A(" << this->a << ", " << this->b << ")析构函数被执行" << endl;
}
};
/* 定义类B */
class B
{
private:
A a1;
A a2;
const int n;
const int m = ;
public:
/* 对象初始化列表:让成员变量从外界接收的方式来初始化 */
B(int x,int y):a1(x,y),a2(,),n()
{
cout << "B(int x,int y)有参构造函数被执行" << endl;
}
~B()
{
cout << "~B()析构函数被执行" << endl;
}
}; int main()
{
B b(, ); return ;
}
4.构造函数和析构函数的执行顺序
- 当类中有成员是其他类的对象时,首先调用成员变量的构造函数,调用顺序和成员变量的定义顺序一致。成员变量的构造函数统统执行完毕后,再调用该类的构造函数。
- 析构函数的执行顺序是“倒关”的方式,即先与构造函数的执行顺序相反。
五,拷贝构造函数的深拷贝和浅拷贝
1.拷贝构造函数的执行原理
拷贝构造函数有四种调用方式,当我们不写拷贝构造函数的时候,C++默认的帮我们写了拷贝构造函数,其函数体实现的是简单的成员变量的值的拷贝。这种默认的拷贝方式,我们称为浅拷贝,即只是简单的复制成员变量的值到另一个对象中。
2.深拷贝问题的抛出
当我们的成员变量是动态分配的一组堆内存的时候,这个时候C++默认的为我们写的拷贝构造函数把成员变量的值进行了复制,那么副本也会指向原始对象所分配的堆内存,当我们在析构函数中释放堆内存的时候,就会发生两次析构现象(一次是原始对象释放堆内存,一次是副本对象释放堆内存)因此造成程序崩溃。
3.深拷贝代码示例
# define _CRT_SECURE_NO_WARNINGS
# include<iostream>
using namespace std; class Student
{
private:
char * name;
int age;
public:
/* 无参构造函数 */
Student()
{
cout << "无参构造函数被执行..." << endl;
}
/* 有参构造函数 */
Student(char * name, int age)
{
/* 在构造函数中分配堆内存 */
this->name = (char *)malloc(sizeof(name) + );
/* 初始化成员变量 */
strcpy(this->name, name);
this->age = age;
cout << "有参构造函数被执行..." << endl;
}
/* 拷贝构造函数 */
Student(const Student &student)
{
/* 重新分配内存 */
this->name = (char *)malloc(sizeof(student.name) + );
/* 初始化成员变量 */
strcpy(this->name, name);
this->age = age;
cout << "拷贝构造函数被执行..." << endl;
}
/* 析构函数 */
~Student()
{
if (this->name != NULL)
{
free(this->name);
this->name = NULL;
this->age = ;
}
cout << "析构函数被执行..." << endl;
}
void print()
{
cout << this->name << " = " << this->age << endl;
} }; int main()
{
Student stu1("王刚", );
/* 此时拷贝构造函数执行,在创建副本的时候进行深拷贝,则不会出现析构问题 */
Student stu2 = stu1; return ;
}
C++中的类和对象(一)的更多相关文章
- 【PHP】PHP中的类与对象
面向对象并不是PHP的关键,但PHP确实能很好的支持面向对象编程,而且类与对象也成为了PHP5的核心组成部分.PHP的面向对象特性让构建大型的复制应用成为可能,有了类与对象,就自然产生了各种编程范式和 ...
- 【JAVA零基础入门系列】Day11 Java中的类和对象
今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...
- Python Cookbook(第3版)中文版:15.19 从C语言中读取类文件对象
15.19 从C语言中读取类文件对象¶ 问题¶ 你要写C扩展来读取来自任何Python类文件对象中的数据(比如普通文件.StringIO对象等). 解决方案¶ 要读取一个类文件对象的数据,你需要重复调 ...
- Java学习笔记十三:Java中的类和对象
Java中的类和对象 一:什么是对象: 总的来说就是"万物皆对象",客观存在的事物皆为对象.是计算机所关注的具体信息. 对象(object)是一件事.一个物体.一个名词,或可以获得 ...
- Java程序设计基础笔记 • 【第7章 Java中的类和对象】
全部章节 >>>> 本章目录 7.1 理解类和对象 7.1.1 对象 7.1.2 抽象与类 7.1.3 类与对象的关系: 7.2 Java中的类和对象 7.2.1 类的定义 ...
- 谈谈Delphi中的类和对象1---介绍几个概念 && 对象是一个地地道道的指针
参考:http://blog.163.com/liang_liu99/blog/static/88415216200952123412180/ 以下的介绍主要针对的是Delphi的面向对象的知识,可能 ...
- 初识python中的类与对象
这篇博客的路线是由深入浅,所以尽管图画的花花绿绿的很好看,但是请先关注我的文字,因为初接触类的小伙伴直接看类的实现可能会觉得难度大,只要耐着性子看下去,就会有一种“拨开迷雾看未来”的感觉了. 一.py ...
- JAVA编程中的类和对象
1:初学JAVA,都知道JAVA是面向对象的编程.笔者这节开始说说类和对象.(实例仅供参考,如若复制粘贴记得修改包名和类名,避免出错) 学习JAVA的快捷键,Alt+/代码补全功能,其实此快捷键启动了 ...
- python中的类,对象,方法,属性等介绍
注:这篇文章写得很好.加底纹的是我自己的理解 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...
- java中的类和对象
Java中的类是一个模板,它用于描述一类对象的行为和状态. 对象则是类中的一个实例,对象有状态(属性)和行为(方法).例如一条狗就是一个对象,他的状态就是他的颜色,名字,品种:他的行为就是叫,摇尾巴, ...
随机推荐
- 【转】 OC基础数据类型-NSSet
原文 : http://www.cnblogs.com/GISerYang/p/3340937.html 1.集合:集合(NSSet)和数组(NSArray)有相似之处,都是存储不同的对象的地址:不过 ...
- 使用gSoap规避和修改ONVIF标准类型结构的解析
ONVIF/gSoap依赖关系及问题 ONVIF是一组服务规范,标准参考 gSoap是一套基于实现SOAP通信接口的工具链 即是,当我们需要访问ONVIF的Web Service或实现对ONVIF部分 ...
- 读书笔记之 - javascript 设计模式 - 组合模式
组合模式是一种专为创建Web上的动态用户界面而量身定制的模式,使用这种模式,可以用一条命令在对各对象上激发复杂的或递归的行为. 在组合对象的层次体系中有俩种类型对象:叶对象和组合对象.这是一个递归定义 ...
- ios开发之xcode6中如何添加pch全局引用文件
xcode6中去掉了默认添加pch文件,这就需要我们自己手动添加pch文件了,添加pch文件是为了一些琐碎的头文件引用,加快编译速度! 下面就说下该如何手动添加pch文件: 1.添加一个文件,在oth ...
- Java学习----集合框架总结
集合框架总结: Collection接口: Set接口: HashSet//对象必须实现hashCode方法,元素没有顺序呢,效率比LinkedHashSet高 LinkedHashSet//是Has ...
- 极简主义,对逻辑操作符||和&&深度运用的理解
丧心病狂的代码压缩好像违背了愉快阅读的本真,所以刨根问底想要了解个究竟,最后发现这不只是前端大牛装逼卖萌的绝技,也是代码洁癖爱好者的利器,毕竟这样看上去确实蛮优雅的; 一开始,我们接触到的代码是这样的 ...
- 实例:用jQuery实现垂直和水平下拉 菜单
主要是利用jQuery来实现垂直菜单和水平菜单.实现效果如图: 第一步,创建一个HTML文件,如图,包含两个ul.当然把jquery库也引入进去了. <!DOCTYPE html> < ...
- 如何使用ASP.NET Web API OData在Oracle中使用Entity Framework 6.x Code-First方式开发 OData V4 Service
环境: Visual Studio 2013 + .Net Framework 4.5.2 1.新建项目 2.安装OData,ODP.NET 安装的包: 下面是部分代码: using System; ...
- 转:使用Mongo Connector和Elasticsearch实现模糊匹配
原文来自于:http://www.csdn.net/article/2014-09-01/2821485-how-to-perform-fuzzy-matching-with-mongo-connec ...
- 会声会影X6-高级运动等效果的练习实践-与您分享...
视频片说明:我在学习X6的视频教程后,做了针对性练习与实 践,我所用的素材取于网络世界-百度下载,视频中的效果有,高级运动;平移缩放,分屏效果,<运用:关键帧,缩放,旋转,加相框,倒 ...