一,类的概念及封装

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++中的类和对象(一)的更多相关文章

  1. 【PHP】PHP中的类与对象

    面向对象并不是PHP的关键,但PHP确实能很好的支持面向对象编程,而且类与对象也成为了PHP5的核心组成部分.PHP的面向对象特性让构建大型的复制应用成为可能,有了类与对象,就自然产生了各种编程范式和 ...

  2. 【JAVA零基础入门系列】Day11 Java中的类和对象

    今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...

  3. Python Cookbook(第3版)中文版:15.19 从C语言中读取类文件对象

    15.19 从C语言中读取类文件对象¶ 问题¶ 你要写C扩展来读取来自任何Python类文件对象中的数据(比如普通文件.StringIO对象等). 解决方案¶ 要读取一个类文件对象的数据,你需要重复调 ...

  4. Java学习笔记十三:Java中的类和对象

    Java中的类和对象 一:什么是对象: 总的来说就是"万物皆对象",客观存在的事物皆为对象.是计算机所关注的具体信息. 对象(object)是一件事.一个物体.一个名词,或可以获得 ...

  5. Java程序设计基础笔记 • 【第7章 Java中的类和对象】

    全部章节   >>>> 本章目录 7.1 理解类和对象 7.1.1 对象 7.1.2 抽象与类 7.1.3 类与对象的关系: 7.2 Java中的类和对象 7.2.1 类的定义 ...

  6. 谈谈Delphi中的类和对象1---介绍几个概念 && 对象是一个地地道道的指针

    参考:http://blog.163.com/liang_liu99/blog/static/88415216200952123412180/ 以下的介绍主要针对的是Delphi的面向对象的知识,可能 ...

  7. 初识python中的类与对象

    这篇博客的路线是由深入浅,所以尽管图画的花花绿绿的很好看,但是请先关注我的文字,因为初接触类的小伙伴直接看类的实现可能会觉得难度大,只要耐着性子看下去,就会有一种“拨开迷雾看未来”的感觉了. 一.py ...

  8. JAVA编程中的类和对象

    1:初学JAVA,都知道JAVA是面向对象的编程.笔者这节开始说说类和对象.(实例仅供参考,如若复制粘贴记得修改包名和类名,避免出错) 学习JAVA的快捷键,Alt+/代码补全功能,其实此快捷键启动了 ...

  9. python中的类,对象,方法,属性等介绍

    注:这篇文章写得很好.加底纹的是我自己的理解 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...

  10. java中的类和对象

    Java中的类是一个模板,它用于描述一类对象的行为和状态. 对象则是类中的一个实例,对象有状态(属性)和行为(方法).例如一条狗就是一个对象,他的状态就是他的颜色,名字,品种:他的行为就是叫,摇尾巴, ...

随机推荐

  1. ORACLE 数据库简单测试

    ORACLE 数据库简单测试 操作系统:Windows 7 – ORACLE:oracle database 10.2.0.4 一.目的 测试 启动监听程序.数据库  非同一个用户的情况,用户是否可以 ...

  2. 多线程 - 线程同步锁(lock、Monitor)

    1. 前言 多线程编程的时候,我们不光希望两个线程间能够实现逻辑上的先后顺序运行,还希望两个不相关的线程在访问同一个资源的时候,同时只能有一个线程对资源进行操作,否则就会出现无法预知的结果. 比如,有 ...

  3. php中的JSON中文处理

    最近在PHP中要输出JSON,上网查了一下,对中文支持不太好,要不就先转成utf-8的编码,再用json_encode生成,客户端还要再utf-8转中文.对于网页已经用GB2312的服务器,不想这样折 ...

  4. ios开发之ios9UIWebView不显示网页问题

    错误描述: App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecu ...

  5. splice从数组中删除指定定数据

    /*从数组中删除指定定数据var somearray = ["mon", "tue", "wed", "thur"]so ...

  6. c#抽象工厂模式

    抽象工厂模式向客户端提供一个接口,使得客户端在不必指定具体类型的情况下,创建多个产品族中的对象.本文采取的仍然是接着以前的那个快餐店的例子. 现在,快餐店经常良好,逐渐发展壮大,为了适合不同地方人的饮 ...

  7. HTML5中的Range对象的研究(转载)

    一:Range对象的概念 Range对象代表页面上的一段连续区域,通过Range对象,可以获取或修改页面上的任何区域,可以通过如下创建一个空的Range对象,如下: var  range = docu ...

  8. JQUERY 键盘事件

    一 一.首先需要知道的是: 1.keydown()keydown 事件会在键盘按下时触发. 2.keypress()keypress 事件会在敲击按键时触发,我们可以理解为按下并抬起同一个按键. 3. ...

  9. wndows常用命令

    1. 远程桌面 mstsc (Microsoft terminal services client)

  10. 20141127 测试使用Word2013书写博客(代码高亮+公式支持)。

      PS :又经过几次测试,发现用于Word2010的高亮插件在Word2013上排版效果不是很好,慎用.不过公式编辑倒是挺方便的 测试使用Word2013书写博客. 大概一个月前,使用WindowL ...