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 ...
随机推荐
- Tomcat 启动 Debug模式
如果debug启动遇到如下错误: ERROR: transport error 202: gethostbyname: unknown host ERROR: JDWP Transport dt_so ...
- PHP-语法(www.w3school.com.cn/php)
写在前面: 假设系统里已安装PHP软件 PHP是一种脚本语言,执行PHP脚本后向浏览器返回纯HTML语言(即后台将.php文件的执行结果以纯HTML的形式返回到前端) ---------------- ...
- 12-C语言字符串
目录: 一.字符串 二.字符串输入输出函数 三.指针数组(字符串数组) 回到顶部 一.字符串 1 一组字符数组,以数组的首地址开始,以ASC码的'\0'结束. 2 字符串与普通数组的区别:普通数组没有 ...
- JVM报错提示
持久代被占满 异常:java.lang.OutOfMemoryError: PermGen space 说明: Perm空间被占满.无法为新的class分配存储空间而引发的异常.这个异常以前是没有的, ...
- poj 3356 AGTC(线性dp)
题目链接:http://poj.org/problem?id=3356 思路分析:题目为经典的编辑距离问题,其实质为动态规划问题: 编辑距离问题定义:给定一个字符串source,可以对其进行复制,替换 ...
- 使用Linux静态库
查看静态库.a文件包含的内容用下面的命令解压: ar x libgdal.a 然后就可以查看文件了: ls adler32.o cpl_recode.o dted_create.o gdalpamra ...
- mybatis级联查询
1.定义四个实体.User Role Privilege Resource,他们之间的对于关系为 2.需求:我通过用户名username查找出该用户对应的角色以及角色对应的权限和资源 3 ...
- Android滑动事件冲突
首先,我们假设这样一个场景:一个ViewPager里面嵌套一个ViewPager,内部滑动方向和外部滑动方向一样时,该怎么解决这一冲突呢? 针对滑动冲突这里给出两种解决方案:外部拦截法,内部拦截法. ...
- stack smashing detect错误修正
运行./a.out程序时候出现如下: *** stack smashing detected ***: ./a.out terminated段错误 (核心已转储) 一般这个错误是由于堆栈错误,很可能是 ...
- JavaScript时钟实例
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...