// 同类之间无私处

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. windows 2003一个网卡绑定多个IP地址

    1.打开“网络连接”,选中需要添加多个IP的“本地连接”-->右键-->“属性”: 2.从“常规”中找到“Internet 协议(TCP/IP)属性”: 3.选择手动设置IP地址.网关.掩 ...

  2. 用saltapi远程操作tomcat启停时,输出日志乱码再解决

    以前解决过一次,是定义LC_ALL为指定编码.但这种思路不完全,因为机器各各不同,系统编码本身不一致(标准化之路漫长啊) 故而在其它一些系统的部署时,用上一次的方案,反而会有错误产生. 于是,按洪军找 ...

  3. Sigma Function 数学 因子求和

    Sigma function is an interesting function in Number Theory. It is denoted by the Greek letter Sigma ...

  4. SPOJ 1811LCS Longest Common Substring

    后缀自己主动机裸题.... Longest Common Substring Time Limit: 2000MS   Memory Limit: Unknown   64bit IO Format: ...

  5. 手动重启weblogic脚本

    手动重启weblogic脚本 pid=`ps -ef|grep fzjc_Admin_Server|grep -v grep|awk '{print $2}'` echo $pid kill -9 $ ...

  6. Java高级程序猿技术积累

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveDczNDQwMDE0Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  7. Could not read from remote repository.

    今天换新电脑,忘了配置git环境,就去gitserver上代替码.然后一直报错,后来就又一次配置了git环境.步骤例如以下 damingwuage:Desktop damingwuage$ ssh-k ...

  8. ZOJ2588 Burning Bridges 无向图的割边

    题目大意:求无向图的割边编号. 割边定义:在一个连通图中,如果删去一个边e,图便变成不连通的两个部分,则e为该图的割边. 求法:边(u,v) 不是割边,当且仅当边(u,v)在一个环内.因此所有不在环内 ...

  9. android 添加新的键值,自定义按键-2【转】

    本文转载自:http://blog.csdn.net/mr_raptor/article/details/8053871 在Android中,上层可使用的键值默认情况下是92个,从0-91:一般情况下 ...

  10. 建模:3D建模

    ylbtech-建模:3D建模 “3D建模”通俗来讲就是通过三维制作软件通过虚拟三维空间构建出具有三维数据的模型.3D建模大概可分为:NURBS和多边形网格. NURBS对要求精细.弹性与复杂的模型有 ...