// 同类之间无私处

2构造函数

3析构函数

4构造函数的种类和析构函数的顺序

结论:析构函数的调用顺序,跟对象的构造顺序相反,谁先构造,谁最后一个被析构。

拷贝构造函数:

注意: 等号写在下面和写在上面是完全不同的。

5拷贝构造函数调用的发生场景

(注意这种情况的执行顺序, 在func函数执行的时候,调用了局部变量的拷贝构造函数

场景四:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

using namespace std;

class Test

{

public:

// 默认构造函数,就是一个无参数的构造函数,

// 如果不显示提供构造函数 系统就是调用默认的构造函数 里面是空函数

// 如果我们提供了一个显示的构造函数,那么默认的构造函数就被隐藏掉了。

/*

Test(){} 默认的构造函数,已经手动提供,默认就被隐藏

*/

// 如果我们提供了一个显示的构造函数 那么默认的构造函数就被隐藏掉了

// 构造函数一旦手动提供 默认将不复存在

Test(int x, int y)

{

m_x = x;

m_y = y;

cout << "调用了有参数的构造函数" << endl;

}

// 无参数的构造函数

Test()

{

m_x = 0;

m_y = 0;

cout << "调用了无参数的构造函数" << endl;

}

// 拷贝构造函数 想通过另一个Test对象 another 将本对象进行拷贝

Test(const Test & another)

{

m_x = another.m_x;

m_y = another.m_y;

cout << "调用了拷贝构造函数" << endl;

}

// 等号操作符

void operator = (const Test & t)

{

m_x = t.m_x;

m_y = t.m_y;

}

void printT()

{

cout << "x: " << m_x << " ,y = " << m_y << endl;

}

// 提供一个析构函数

~Test()

{

cout << "~Test() 析构函数被执行了" << endl;

cout << "(" << m_x << "," << m_y << ")" << "被析构了" << endl;

}

private:

int m_x;

int m_y;

};

// 拷贝构造函数的第一个场景

void test1()

{

Test t1(1, 2);

Test t2(t1);

// 通过t1 给t2 进行赋值

t2.printT();

}

// 拷贝构造函数的第二个场景

void test2()

{

Test t1(1, 2);

Test t2;

t2 = t1; //调用的不是拷贝构造函数, 调用的是 =号操作符,也能够完成将t1的值给t2

// 但不是调用t2的拷贝构造函数

}

// 拷贝构造函数的第三个场景

void func(Test t) // Test t = test1::t1; // 会调用局部变量t的靠别构造函数

{

cout << "func begin..." << endl;

t.printT();

cout << "func end..." << endl;

}

void test3()

{

cout << "test3 begin ..." << endl;

Test t1(10, 20); //创建了一个t1的对象 通过t1的有参数的构造函数

func(t1);

cout << "test3 end..." << endl;

}

// 场景四

Test func2()

{

cout << "func2 begin..." << endl;

Test temp(10, 20);

cout << "func2 end.." << endl;

return temp; //有一个临时的匿名对象 = temp , 把temp的数据给到了临时的匿名对象

// 会调用这个临时匿名对象的拷贝构造函数 把temp传进去。

}

void test4() {

cout << "test4 begin..." << endl;

func2();

// 匿名对象在此被析构了 如果一个匿名的临时对象 没有任何变量去接受它

// 编译器认为这个临时匿名对象没有用处

// 编译器会立刻销毁这个临时的匿名对象

cout << "test4 begin..." << endl;

}

int main(void)

{

test4();

return 0;

}

(红圈表示匿名函数析构)

6默认构造函数和深拷贝浅拷贝

7中午回顾

// 浅拷贝析构的时候 可能会出现问题重复析构 两次 引出问题

8构造函数的初始化列表

结论:

// 类内部  的对象初始化的顺序  跟 对象定义的顺序一样 跟初始化列表中的顺序无关

// 析构的顺序就跟构造的顺序相反

9 强化练习1

12new和delete

new 和 delete

malloc 和 free

在堆上分配和释放的时候功能是类似的。

区别:new和delete会调用构造函数和析构函数

malloc和free不会

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

using namespace std;

class Test

{

public:

Test()

{

m_a = 0;

m_b = 0;

cout << "0,0 构造" << endl;

}

Test(int a, int b)

{

m_a = a;

m_b = b;

cout << "a = " << m_a << ", b = " << m_b << "构造" << endl;

}

void setA(int a)

{

m_a = a;

}

void setB(int b)

{

m_b = b;

}

void printT()

{

cout << "a = " << m_a << ", b =" << m_b << endl;

}

~Test()

{

cout << "a = " << m_a << ", b = " << m_b << "析构" << endl;

}

private:

int m_a;

int m_b;

};

// C语言中

void test1()

{

int *p = (int *)malloc(sizeof(int));

*p = 10;

cout << *p << endl;

if (p != NULL) {

//free(p);

delete p; // delete可以释放malloc开辟的内存

}

int *array_p = (int *)malloc(sizeof(int) * 10);

for (int i = 0; i < 10; i++)

{

array_p[i] = i + 10;

}

for (int i = 0; i < 10; i++)

{

cout << array_p[i] << endl;

}

if (array_p != NULL)

{

free(array_p);

}

cout << " ------- " << endl;

Test *tp = (Test *)malloc(sizeof(Test));// 不会调用对象的构造函数

tp->setA(10);

tp->setB(20); // malloc 出来的对象指针,只能够通过成员函数来进行初始化

tp->printT();

if (tp != NULL)

{

free(tp); //不会调用对象的析构

}

}

// malloc 和 free 在对于普通变量是可以混合使用的 但是malloc和free是函数

// new和delete是操作符。不是一个函数(没有压栈出栈过程)

// C++中的new delete

void test2()

{

//new 能够完成所有malooc的需求

int *p = new int; // 在堆上动态开辟4个字节

*p = 10;

cout << *p << endl;

if (p != NULL)

{

//delete p; //delete一个变量

free(p); //用new开辟的内存 free也能够释放

}

cout << "----" << endl;

int *array_p = new int[10];

for (int i = 0; i < 10; i++)

{

array_p[i] = i + 10;

}

for (int i = 0; i < 10; i++)

{

cout << array_p[i] << endl;

}

if (array_p != NULL)

{

delete[] array_p; // delete一个数组

}

cout << "------" << endl;

//Test *tp2 = new Test(10, 20); // 调用了有参数的构造函数//new 在创建一个对象的时候会调用对象的构造函数

Test *tp2 = new Test; //调用了无参构造函数

tp2->printT();

if (tp2 != NULL)

{

delete tp2; // delete在释放一个对象指针的时候 会调用对象的析构函数

}

}

int main(void)

{

//test1();

test2();

return 0;

}

13静态成员变量

在C语言中

static如果修饰全局变量 该变量不可以被别的文件访问

修饰局部变量 生命周期随着生命周期销毁销毁

修饰函数:

(普通 函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。因此定义静态函数有以下好处:
  <1> 其他文件中可以定义相同名字的函数,不会发生冲突。
  <2> 静态函数不能被其他文件所用。)

(static 貌似是在编译的时候就确定的,不是运行时)

复习:

https://www.cnblogs.com/getyoulove/p/3656184.html

共享同一块静态区域

14 static成员变量练习

定义 Box 所有的高度都一样

(通过查看大小 说明static修饰的成员变量不属于对象中,而是在全局区开辟的)

15 static修饰成员函数

main函数中:

(这里没有对象,是直接用类调用的)

16 static总结和static成员变量的大小

结论:决定类大小的就是类的普通成员变量 没有函数和全局变量

明天讲为什么

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量的更多相关文章

  1. C++构造函数初始化列表与构造函数中的赋值的区别

    C++类中成员变量的初始化有两种方式:构造函数初始化列表和构造函数体内赋值. 一.内部数据类型(char,int……指针等) class Animal { public: Animal(int wei ...

  2. C++ 构造函数_初始化列表

    构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class Student { public: //构造函数初始化列表 Stude ...

  3. C++(二十八) — 构造函数的初始化列表

    1.解决的问题: 在 B 类中,组合了一个 A 类对象,其中A类设计了构造函数.由于构造函数的调用规则,设计了构造函数就必须调用,但在定义B类时没有机会初始化A,因此采用构造函数的初始化列表来解决. ...

  4. c++构造函数的初始化列表(翁恺c++公开课[13])

    初始化列表形式: class Point { private: const float x,y; Point(float xa = 0.0, flato ya = 0.0):y(ya),x(xa) { ...

  5. C++ //构造函数调用规则 //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) //析构函数(空实现) //拷贝函数(值拷贝) //2.如果我们写了有参构造函数 编译器就不会提供默认构造函数 但是会提供拷贝构造函数 //3.如果我们写了拷贝函数 编译器就不再提供 默认 有参 构造函数

    //构造函数调用规则 #include <iostream> using namespace std; //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) ...

  6. 【C++对象模型】构造函数语意学之二 拷贝构造函数

    关于默认拷贝构造函数,有一点和默认构造函数类似,就是编译器只有在[需要的时候]才去合成默认的拷贝构造函数. 在什么时候才是[需要的时候]呢? 也就是类不展现[bitwise copy semantic ...

  7. c++ 关于类构造函数的初始化列表

    除了性能问题之外,有些时场合初始化列表是不可或缺的,以下几种情况时必须使用初始化列表 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面 引用类型,引用必须在定义的时候初始化,并且不能重 ...

  8. C++中构造函数的初始化列表(const、引用&变量初始化)

    1. 构造函数执行分为两个阶段: a.初始化阶段(初始化) 初始化阶段具体指的是用构造函数初始化列表方式来初始化类中的数据成员. ClassXX:val(a),key(b){}; b.普通计算阶段(赋 ...

  9. 从初始化列表和构造函数谈C++的初始化机制

    来源:http://blog.csdn.net/theprinceofelf/article/details/20057359 前段时间被人问及“初始化列表和构造有什么区别?”我竟一时语塞,只好回头 ...

随机推荐

  1. 洛谷 P1560 [USACO5.2]蜗牛的旅行Snail Trails(不明原因的scanf错误)

    P1560 [USACO5.2]蜗牛的旅行Snail Trails 题目描述 萨丽·斯内尔(Sally Snail,蜗牛)喜欢在N x N 的棋盘上闲逛(1 < n <= 120). 她总 ...

  2. @requestbody @responsebody详解

    @requestbody @responsebody详解 会唤起spring mvc的httpmessageconveter转换类进行数据转换 简介: @RequestBody 作用: i) 该注解用 ...

  3. ZOJ 3209

    精确覆盖 #include <iostream> #include <cstdio> #include <cstring> #include <algorit ...

  4. 搭建单机CDH环境,并更新spark环境

    搭建单机CDH环境,并更新spark环境 1,安装VMWare Player,http://dlsw.baidu.com/sw-search-sp/soft/90/13927/VMware_playe ...

  5. [MSSQL]採用pivot函数实现动态行转列

    环境要求:2005+ 在日常需求中常常会有行转列的事情需求处理.假设不是动态的行,那么我们能够採取case when 罗列处理. 在sql 2005曾经处理动态行或列的时候,通常採用拼接字符串的方法处 ...

  6. Linux命令(一)——简单命令

    一.简单命令 1.pwd命令 显示当前工作的全路径名. 2.date命令 显示系统当前的日期和时间. 3.who命令 显示当前已登录到系统的所有用户名,及其终端名和登录到系统的时间. 4.cal命令 ...

  7. JDBC中向数据库录入汉字产生乱码的解决办法

    在近期的课程设计中遇到在eclipse中向数据库中录入数据,产生的汉字乱码现象,在这里提供一条解决的方法: 只需连接地址URL中数据库名后面添加“?characterEncoding=utf-8”即可 ...

  8. 0=='aa'的结果是true

    来源于一道面试题: PHP的类型转换规则 1.如果是一个数字与一个字符串进行比较,那么会把字符串转换为数字再比较 2.字符串的转换规则,若字符串以数字开头,则取开头数字作为转换按结果,若无,则取0

  9. 关于PHP浮点数之 intval((0.1+0.7)*10) 为什么是7

    PHP是一种弱类型语言, 这样的特性, 必然要求有无缝透明的隐式类型转换, PHP内部使用zval来保存任意类型的数值, zval的结构如下(5.2为例): struct _zval_struct { ...

  10. 图像处理中的数学原理具体解释20——主成分变换(PCA)

    欢迎关注我的博客专栏"图像处理中的数学原理具体解释" 全文文件夹请见 图像处理中的数学原理具体解释(总纲) http://blog.csdn.net/baimafujinji/ar ...