![](https://img-blog.csdnimg.cn/20201014180756724.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C++
文章平均质量分 83
学习C++时的一些记录,方便日后查询
tusdddd
这个作者很懒,什么都没留下…
展开
-
友元
友元对于一个类来说,类外部的对象想要访问类中的private成员只有通过公共访问函数来实现。这在有些时候会很不方便,这个时候就可以使用友元的方式使一些特定的外部对象也能访问类内的private成员。友元分为三种,分别为友元函数,友元类和友元成员函数。友元函数如果一个类将一个函数声明为自己的友元函数,则表示该函数能够直接访问本类中的私有成员。声明函数为友元函数在类的声明中完成,而函数的定义跟普通函数一样,不需要额外修改。并且同一个函数可以同时是多个类的友元函数,例如:class Fractor; //原创 2020-12-08 09:01:07 · 226 阅读 · 0 评论 -
模板类
模板类跟之前介绍过的模板函数类似,模板类并不是一个类,而是像编译器解释了如何生成一个类。所以,声明一个模板类的时候是不会占用内存的,只有在将模板具体化,形成真正可以使用类时,才会为该类分配内存。基本语法template <typename T>class stack{ private: static int num = 0; int cap; T * st;};注意,当类模板中存在静态变量的时候,并不是所有由该模板初始化出来的类都共享这一个变量。而是所有由相同参数具原创 2020-12-07 19:08:10 · 3407 阅读 · 0 评论 -
多重继承
多重继承多重继承就是一个派生类同时继承多个基类,同样也分为公有继承,私有继承和保护继承三种,这三种继承可以实现的关系跟单继承一样,但是多重继承会带来很多新的问题,这里以公有继承为例:假设我们要实现下面的继承关系:这会带来一个问题。前面说到,使用单继承的时候,派生类之中会有一个基类,派生类只是在基类的数据上额外增加了一些数据。也就是说每一个从基类派生出来的派生类对象都会维护一个基类对象,这就是问题所在。在上面的继承关系中,Worker和Adult都继承了同一个基类,而Singer同时继承了Worker原创 2020-12-04 14:39:21 · 997 阅读 · 0 评论 -
多态继承11
多态继承多态继承是C++中实现代码重用的一个重要方法。例如最刚开始的时候定义了一个基础类Base:class Base{ private: string name; public: Base(string n): name(n){} void show(){ cout << "Using base function: " << name << endl; }};这个类只是实现了最基本的功能,但是如果临时想为该类添加一个新的功能,就要在B原创 2020-12-04 10:29:08 · 328 阅读 · 0 评论 -
多态继承
多态继承多态继承是C++中实现代码重用的一个重要方法。例如最刚开始的时候定义了一个基础类Base:class Base{ private: string name; public: Base(string n): name(n){} void show(){ cout << "Using base function: " << name << endl; }};这个类只是实现了最基本的功能,但是如果临时想为该类添加一个新的功能,就要在B原创 2020-12-02 21:03:22 · 416 阅读 · 0 评论 -
构造函数初始化列表
构造函数初始化列表与普通构造函数的区别构造函数初始化列表用于在显式初始化类成员。在平常的使用构造函数创建对象时,如果对象中将另一个对象作为成员,那么在调用构造函数之前,编译器会用成员对象的默认构造函数进行初始化。如果不想让编译器用默认的构造函数进行初始化,就要使用构造函数初始化列表来显式规定成员对象的初始化形式。构造函数进行的操作是,将成员先初始化,再用给定值赋值给初始化后的成员,而构造函数初始化列表则是直接对成员进行初始化,两者之间的区别跟下面两种创建变量的方式区别类似://在创建的时候直接初始化原创 2020-11-27 21:18:51 · 1282 阅读 · 0 评论 -
定位New与对象
定位new与对象当使用定位new运算符为对象分配内存时,注意调用对象的析构函数。因为delete运算符必须跟new配套使用,而不是跟定位new配套使用。所以使用定位new为对象分配空间并初始化对象之后,不能用delete清除对象。这时如果对象的构造函数中使用new申请了内存,就会导致内存泄漏,因为不能使用delete清除对象。例如:class BadString{ private: int len; char * str; public: BadString(); BadString原创 2020-11-27 10:11:32 · 103 阅读 · 0 评论 -
遇到的问题
遇到的问题这个文章用于记录在学习和使用C++的时候遇到的一些问题,以及解决方法,记载了一些非常零散的知识点,没有主题。用new申请结构体,并初始化结构体中的数组在C++11中,有一种新的方法在用new运算符申请结构体内存的同时对其初始化。其格式为:struct car{ int years; double price;};car * p = new car{3, 23.5};但是如果结构体中包含了字符数组(字符串),就不能使用这种格式,例如:struct car{原创 2020-11-26 14:16:50 · 79 阅读 · 0 评论 -
复制构造函数
复制构造函数提出背景C++中的new和delete关键字给了用户更大的自由对内存进行管理,但是如果使用不当就很容易造成内存泄漏。在创建和使用类的时候,需要额外小心,因为对类的创建和销毁行为的管理不当是造成内存泄漏的重要原因。下面是一个反面教材:class BadString{ private: static int num; //用于记录当前创建的实例化个数,这个值在每个构造函数中都会被+1 char * str; int len; public: BadString(); B原创 2020-11-25 21:35:09 · 146 阅读 · 0 评论 -
new运算符的使用
new运算符的使用基本语法C++中使用new运算符来申请内存,其基本格式为:int * p1 = new int; //分配一个未初始化的int内存int * p2 = new int(6); //分配一个int内存,并用括号内的值初始化int * p3 = new int [3] {1,2,3}; //分配一组int内存,并用花括号内的值初始化也可以使用new运算符为一个结构体申请内存,这里有一个坑,详情可以看这里。例如:struct car{原创 2020-11-25 19:14:13 · 2175 阅读 · 0 评论 -
自定义类的类型转换
自定义类的类型转换C++中,不同类型之间在赋值时可能发生自动类型转换,例如int x = 2.4;这个语句将会把2.4转换成int类型然后再赋值给x,这一过程发生了自动类型转换。原始类型向自定义类的转换(使用构造函数)对于用于自己定义的类,C++也可以进行自动类型转换,下面是一个例子:class Stock{ private: double price; public: Stock(double p){ price = p; }原创 2020-11-24 19:42:30 · 1267 阅读 · 0 评论 -
运算符重载
运算符重载提出背景C++中的基本类型可以使用+,-等运算符对其直接进行操作,这样非常方便。但是默认情况下不能直接用运算符对对象进行操作。例如:class Stock{ private: double price; public: Stock(double); Stock();};对于这个类的对象,如果我们想将两个对象的price成员的值相加,就只能定义一个sum()函数来实现操作。这样我们在使用的时候也要调用这个函数。注意运算符的左原创 2020-11-24 08:59:04 · 433 阅读 · 0 评论 -
对象和类
对象和类基本概念和语法根据面向对象的定义,类是一系列数据和针对这些数据的操作的集合。由于C++对结构体进行了扩展,所以在功能上类跟结构体的作用完全一致。但是在实际的使用上,结构体只用来封装数,而类用来表示一个对象的模板。类的声明中分为两个部分,私有和公有,两个部分声明的成员有相应的可访问性。类的声明跟定义分开,如果在声明类的同时定了函数,该函数就会被编译成内联函数。并且在开发的时候一般将类的定义写在头文件中,对应类的定义写在一个单独的代码源文件中,编译的时候将多个文件进行编译即可。在类中定义的函数原创 2020-11-17 18:46:09 · 59 阅读 · 0 评论 -
new运算符的使用
new运算符的使用基本语法C++中使用new运算符来申请内存,其基本格式为:int * p1 = new int;int * p2 = new int(6);int * p3 = new int [3] {1,2,3};也可以使用new运算符为一个结构体申请内存,这里有一个坑,详情可以看这里。例如:struct car{ int years; double price;};car * p = new car{3, 23.5};一旦使用new申请了内存就要妥善管理,如原创 2020-11-16 17:39:23 · 254 阅读 · 0 评论 -
遇到的问题
遇到的问题这个文章用于记录在学习和使用C++的时候遇到的一些问题,以及解决方法,记载了一些非常零散的知识点,没有主题。用new申请结构体,并初始化结构体中的数组在C++11中,有一种新的方法在用new运算符申请结构体内存的同时对其初始化。其格式为:struct car{ int years; double price;};car * p = new car{3, 23.5};但是如果结构体中包含了字符数组(字符串),就不能使用这种格式,例如:struct car{原创 2020-11-13 19:46:58 · 220 阅读 · 0 评论 -
作用域和持续性
作用域和持续性C++中持续性表示变量在程序运行的过程中什么时候被创建和销毁,作用域表示表示变量可以从哪里被访问到。持续性C++中有四种不同持续性的变量:自动存储持续性:例如在代码块中定义的变量,随着初始化语句的执行而创建,随着代码块的结束而销毁。静态存储持续性:在代码块中用static关键字修饰的变量和在代码块外声明的变量。它们在编译的时候被初始化,在程序退出的时候才销毁。线程存储持续性:使用thread_local声明的变量,线程退出的时候销毁。动态存储持续性:使用new运算符创建的变量,原创 2020-11-12 19:44:17 · 119 阅读 · 0 评论 -
函数模板
函数模板基本语法有时候对于多种数据类型可能需要执行相同的操作,如果没有函数模板,则需要为各个数据类型单独实现相应的函数,这样会导致代码的编写非常繁琐。有了函数模板之后只需要为所有的类型实现一个公用的函数模板即可,编译器会根据该模板为不同的类型生成相应的函数。我们声明一个函数模板的时候不创建函数,只是提供创建函数的模板,当需要使用到函数的时候,编译器才会根据模板创建函数。下面是声明一个函数模板的基本格式:template <class T> //这里class也可以用typename代替,原创 2020-11-10 21:08:11 · 105 阅读 · 0 评论 -
函数重载
函数重载基本用法当一个函数需要根据不同的情况接收不同的参数时,以前的做法通常是为每一种可能的情况单独建立一个函数名,这样会造成代码非常臃肿。而有了函数重载之后,就可以用同一个函数名进行调用,虽然还是要根据不同的参数类型进行单独的实现,但是在调用的时候使用相同的函数名,并根据情况传入不同的参数即可,这样使得代码更加简洁。例如:void print(const char * str, int width); //#1void print(double d, int width);原创 2020-11-09 20:23:25 · 163 阅读 · 1 评论 -
引用参数
引用参数概念其本质是一个变量的别名,如果对一个变量声明了引用变量,那么该引用变量只能是该变量的别名,任何针对引用变量的操作都会被应用到原变量上。因为其本质是一个变量的别名,所以声明的时候只能对将变量赋值给引用变量,并且引用变量在声明的时候必须初始化,例如:int a;int & ref = a;a = 10;printf("a = %d\n", a);ref++;printf("ref = %d\n", ref);在初始化引用变量之后,该引用变量便与用于初始化的变量绑定了,如果原创 2020-11-09 18:52:04 · 3299 阅读 · 0 评论 -
函数指针
函数指针基本语法跟数据一样,函数也存储在内存中,有自己的地址,有时候可以将一个函数的地址传入到另一个函数中,从而可以在另一个函数中调用该函数。这样做的好处是,在不同的时候可以根据不同的情况调用不同的函数来达到对应的目的。例如:int cmp1(int x, int y);int cmp2(int x, int y);int max(int x, int y, int (*cmp)(int, int));这里max函数中的int (*cmp)(int, int)定义的就是一个函数指针,其中最左边原创 2020-11-08 21:13:05 · 106 阅读 · 0 评论 -
函数和二维数组
函数与二维数组如果要将一个二维数组传入一个函数,其函数的形参声明形式应该是:int sum(int (*arr)[4], int size);\\为了提高可读性,也可以写成这样的形式int sum(int arr [][4], int size);这里int (*arr)[4]表示arr是一个数组,数组的元素是指向另一个由四个元素组成的数组。也就规定了二维数组的列数为4,这是C++的语言性质。这里int (*arr)[4]中的括号不能去除,如果去除,就表示声明的是一个由四个指向int类型的指针原创 2020-11-08 21:12:18 · 425 阅读 · 0 评论