c++特殊函数
C++中NULL不能写作小写,NULL的值为零,也可以写作0
在自己写的复制构造函数中不改变原对象,所以传进来的参数可以设为const类型的,这样可以保证传进来的对象不被改变
比如A(const A &a)
同时注意,如果再函数体中不改变任何变量,那么这个函数也可以设为const,也就是把函数体前(大括号前面)面加上const
编译器提供默认构造函数和析构函数,同时也提供复制构造函数,编译器提供的默认复制构造函数只是把传递进来的对象的每个成员变量复制到新对象的成员变量中去,然后两个对象中的变量均指向存放类成员变量的那块内存区域,假如该变量不是指针变量一般不会出错,假如该变量是指针变量,释放一个对象的内存空间的时候另一个对象会受到影响,因为本来两个对象中的指针指向同一块内存区域,释放其中一个对象的时候,其中的指针变量指向的内存区域也被释放,这时候没被释放的对象中的指针变量成员就成为一个迷途指针,找不到原来指向的那个对象的变量了(这时候需要自己写深层复制构造函数函数,代码在下面)
下面用代码演示默认复制构造函数:
#include <iostream>
using namespace std;
class A
{
public:
A(){x = new int; *x = ;}
~A() {delete x; x = NULL;}
A(const A &a)
{
cout << "复制构造函数执行!\n" << endl;
x = a.x; //其中x是新复制的对象的成员,可以用this.x表示,不加this的时候,系统默认加上
}//我们不写复制构造函数的时候系统自动为我们加上这样一个复制构造函数
void print()const{cout << *x << endl;}
void set(int i){*x = i;}
private:
int *x;
};
int main()
{
A *a = new A;
a->print();
A b = (*a);
b.print();
a->set();
b.print();
delete a;
b.print();
return ;
}
假设自己写构造函数就不会出现浅层复制造成的错误:(上述代码改为深层复制后代码如下)
#include <iostream>
using namespace std;
class A
{
public:
A(){x = new int; *x = ;}
~A() {delete x; x = NULL;}
A(const A &a)
{
cout << "复制构造函数执行!\n" << endl;
x = new int;
*x = *(a.x);
}
int get()const{return *x;}
void set(int i){*x = i;}
private:
int *x;
};
int main()
{
A *a = new A;
cout << "*(a.x):" << a->get() << endl;
A b = (*a);
cout << "*(b.x):" << b.get() << endl;
a->set();
cout << "*(a.x):" << a->get() << endl;
cout << "*(b.x):" << b.get() << endl;
delete a;
cout << "删除a之后*(b.x):" << b.get() << endl;
return ;
}
复制构造函数会完成两个对象之间的拷贝
隐式转换有时候会造成一些错误,需要关闭隐式转换的话可以在构造对象的时候加上关键词explicit,不加explicit的话默认可以进行隐式转换
我们可以把数字当作对象赋给另一个对象,这样在对该赋值表达式进行计算的时候,首先要对数字进行类型转换,同时判断该类的构造函数的参数是否与数字的类型匹配,假如匹配则调用 构造函数创建一个临时对象,跟着将该临时对象赋给复制操作左边的对象,最后调用析构函数删除临时对象(判断匹配然后转换的过程叫做隐式转换)
#include <iostream>
using namespace std;
class A
{
public:
explicit A(int x){i = x; cout << "构造函数执行!" << endl;}
~A() {cout << "析构函数执行!\n";}
void get() {cout << i << endl;}
private:
int i;
};
int main()
{
A a();
a.get();
a = A(); //这里也可以写成a = 1000;这样的话该对象的构造函数前面不能加explicit,
return ; //因为加上explicit之后,该对象就不能进行隐式类型转换了
}
delete会调用析构函数删除在堆中创建的空间
#include <iostream>
using namespace std;
//本代码演示了delete 会调用析构函数来释放new运算符创建的内存空间
//本代码还演示了在堆中创建对象
//注意在堆中创建的对象必须手动删除,本代码没有删除第二个对象
class A
{
public:
A(){cout << "构造函数执行!" << endl;}
~A(){cout << "析构函数执行!\n";}
void set(int a, char b)
{
i = a;
j = b;
}
void print()
{
cout << i << " " << j << endl;
}
private:
int i;
char j;
};
int main()
{
A *a;
a = new A; //在堆中创建对象
a->set(, 'a');
a->print();
delete a;
cout << endl << endl;
A *b = new A;
b->set(, );
return ;
}
复制构造函数:(注:如果不写复制构造函数的话系统自动加上默认复制构造函数)
#include <iostream>
using namespace std;
class A
{
public:
A(){}
A(A&one){n = one.n; m = one.m;} //默认构造函数就是这样写的,假设我们不写,系统自动加上
A(int i, int j){n = i; m = j;}
void print()
{
cout << "n: " << n << " m: " << m << endl;
}
private:
int n, m;
};
int main()
{
A a(, );
a.print();
A b(a); //这时候a的值就传给b了
b.print();
return ;
}
函数声明的时候可以只写参数类型,不写参数名
当函数的参数缺省的时候,如果给函数传递参数,则函数的参数为传进来的数,否则
函数的参数为默认值
函数参数缺省和函数重载的使用有几分相像,但是不同:
具有默认参数的函数重载的是参数的数值,而重载函数重载的是参数的类型。
1:普通函数参数的缺省
#include <iostream>
using namespace std;
void fun(int n = , int m = )
{
cout << "n:" << n << " m:" << m << endl;
} int main()
{
fun(); //输出默认参数0 0
fun(,);//输出参数1, 2
return ;
}
2:类中方法的参数缺省
#include <iostream>
using namespace std;
class A
{
public:
void set(int = , int = );
void count(bool = false);
private:
int w;
int h;
};
void A::set(int width, int height)
{
w = width;
h = height;
}
void A::count(bool val)
{
if(val)
cout << "val的值为真时:" << w*h << endl;
else
cout << "val的值为假时:" << w*h/ << endl;
}
int main()
{
A a;
a.set();
a.count();
a.count(true);
a.set(,);
a.count();
a.count(true);
return ;
}
不仅普通函数可以重载,构造函数也可以重载:
/*构造函数也可以重载*/
#include <iostream>
using namespace std;
class rectangle
{
public:
rectangle(){cout << "构建一个长方形\n";}
rectangle(int l, int w){ length = l; width = w; cout << "长方形的面积为:" << length*width << endl;}
rectangle(int l, int w, int h){length = l; width = w; height = h; cout << "长方体的体积为:" << l*w*h << endl;}
private:
int length;
int width;
int height;
};
int main()
{
rectangle();
rectangle(, );
rectangle(, , );
return ;
}
对成员变量初始化的另一种方式
在函数体前面也就是函数名后面加冒号同时加上变量和对应的初始化值,
这种方法是对成员变量的初始化,而不是赋值
/*可以在构造函数头对常量和引用初始化;这种方法和在函数中对变量赋值都是给成员变量一个值,但是有所不同
1:在函数头实际上是初始化
2:在函数中的语句实际是赋值语句
区分赋值语句和初始化语句
初始化:即定义的时候进行赋值 比如说你定义的某个对象的成员是常量,那么在该对象的方法体中对该常量赋值会报错
但是在函数头对该常量赋值就会正常运行
由此我们可以看出在函数头和在函数中给一个变量赋值的区别
在函数头的实际是初始化语句,在函数中对对象的成员赋值才是赋值语句*/ #include <iostream>
using namespace std;
class rectangle
{
public:
rectangle():length(), width(){cout << "长方形的面积为:"<< length * width;}
private: //在函数名字后面加上冒号,然后是给每个变量赋的值,如果有多个赋值语句,中间用逗号隔开
const int length; //因为在函数名字后面加冒号写上给他们的值得话相当于对成员变量初始化,所以不会报错
int width; //如果直接在函数体中对常量赋值会报错,因为不能对常量赋值,只能对常量初始化
};
int main()
{
rectangle();
return ;
}
构造函数的初始化顺序:
它是按照定义时候的成员列表中的初始化顺序来的,析构的时候是先析构最后构造的那个成员
#include <iostream>
using namespace std;
/*构造函数的初始化顺序,它是按照成员列表的初始化顺序来的,并不看你在构造函数中先对谁赋值 然而析构函数是首先析构成员列表中最后构造的函数*/
class demo
{
public:
demo(){x = ; cout << "demo的默认构造函数" << endl;}
demo(int i){x = i; cout << "demo的带一个参数的构造函数" << x << endl;}
~demo(){cout << "demo的默认析构函数" << endl;}
int get(){return x;}
void set(int i) {x = i;}
private:
int x;
};
class rectangle
{
public:
rectangle(){x = ; cout << "rectangle的默认构造函数" << endl;};
rectangle(int i, int j, int k):x(i), width(j), length(k)
{
cout << "rectangle的带三个参数的构造函数!" << "长方形的面积为:" << length.get()*width.get() << endl;
}
~rectangle(){cout << "rectangle的默认析构函数" << x << endl;}
private:
int x;
demo width;
demo length;
};
int main()
{
rectangle a(, , );
return ;
}
再强调下常量和引用必须初始化,如果是类中的对象的话,需要按照在函数体前面赋值的方法初始化
#include <iostream>
class A
{
public:
A(int a, int b):num(a),total(b)
{
/*
下面的写法不对,因为常量和引用只能初始化不能赋值
num = a;
total = b;
*/
}
private:
const int num;
int &total;
};
int main()
{
A a(, );
return ;
}
c++特殊函数的更多相关文章
- Qt Creator+MinGW+boost特殊函数的使用示例
Qt Creator+MinGW+boost特殊函数的使用示例: 先编译和安装boost: bootstrap.bat gcc .\b2 --toolset=gcc --prefix=E:\boost ...
- 数字信号处理专题(2)——利用FPGA进行基本运算及特殊函数定点运算
一.前言 FPGA以擅长高速并行数据处理而闻名,从有线/无线通信到图像处理中各种DSP算法,再到现今火爆的AI应用,都离不开卷积.滤波.变换等基本的数学运算.但由于FPGA的硬件结构和开发特性使得其对 ...
- Day10 Python基础之特殊函数(八)
一些特殊函数 1.递归函数(recursion) 递归函数的定义:在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 递归函数的优点:是定义简单,逻辑清晰.理论上,所 ...
- Kotlin入门(11)江湖绝技之特殊函数
上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...
- 以太坊系列之十四: solidity特殊函数
solidity中的特殊函数 括号里面有类型和名字的是参数,只有类型是返回值. block.blockhash(uint blockNumber) returns (bytes32): hash of ...
- python特殊函数
__doc__ 类(实例).__doc__ 类的描述信息 '''class des''' __module__ 类(实例).__module__ 表示当前操作的对象在那个模块 __class__ ...
- 08.C语言:特殊函数
C语言:特殊函数 1.递归函数: 与普通函数比较,执行过程不同,该函数内部调用它自己,它的执行必须要经过两个阶段:递推阶段,回归阶段: 当不满足回归条件,不再递推: #include <stdi ...
- Js基础知识(作用域、特殊函数---自调、回调、作为值的函数)
15.作用域 概念: 规定变量或函数的可被访问的范围和生命周期 分类: 全局作用域 -就是指当前整个页面环境: 局部作用域(函数作用域) -就是指某个函数内部环境 l 变量的作用域 全局变量 - 定义 ...
- 常见PHP危险函数及特殊函数
PHP代码执行函数 - eval & assert & preg_replace mixed eval ( string $code ) 把字符串 $code 作为PHP代码执行. 很 ...
- SciPy 特殊函数
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
随机推荐
- mysql 组合索引
MySQL单列索引是我们使用MySQL数据库中经常会见到的,MySQL单列索引和组合索引的区别可能有很多人还不是十分的了解,下面就为您分析两者的主要区别,供您参考学习. 为了形象地对比两者,再建一个表 ...
- LintCode-编辑距离
题目描述: 给出两个单词word1和word2,计算出将word1 转换为word2的最少操作次数. 你总共三种操作方法: 插入一个字符 删除一个字符 替换一个字符 样例 给出 work1=" ...
- Microsoft Accelerator for Windows Azure Alum Azuqua 今天启动
云最大的一个优势就是,它使开发人员比以往任何时候都更迅速.更灵活.在 Windows Azure 中开发应用程序时,工程师无需考虑架设服务器.规划容量或进行日常维护.相反,他们可以专注于提出假设 ...
- vs2013 linq to mysql
安装文件 1.下载安装文件 2.创建项目 3.创建mysql数据连接 4.新建ADO.NET数据模型 项目实现代码 using (WorkerContainer db = new WorkerCont ...
- 全栈JavaScript之路(七)学习 Comment 类型节点.
凝视 在DOM中,用 Comment 类型 节点表示, 构造器函数为: function Comment(){[native code]}. comment 节点的特征: nodeType:8 no ...
- JS中onload的各种使用
1.最简单的调用方式 直接写到html的body标签里面,如: <html> <body onload="func()"> </body> &l ...
- ping的意思
Ping是测试网络联接状况以及信息包发送和接收状况非常有用的工具,是网络测试最常用的命令.Ping向目标主机(地址)发送一个回送请求数据包,要求目标主机收到请求后给予答复,从而判断网络的响应时间和本机 ...
- Node.js入门-Node.js 介绍
Node.js 是什么 Node.js 不是一种独立的语言,与 PHP,Python 等"既是语言优势平台"不同,它也不是一个 JavaScrip 框架,不同于 CakePHP,D ...
- 纯CSS写九宫格样式,高宽自适应正方形
<!DOCTYPE html><html> <head> <meta charset="utf-8"> ...
- FreeCodeCamp:Slasher Flick
要求: 打不死的小强! 返回一个数组被截断n个元素后还剩余的元素,截断从索引0开始. 结果: slasher([1, 2, 3], 2) 应该返回 [3]. slasher([1, 2, 3], 0) ...