欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > C++基础知识

C++基础知识

2025/2/24 11:10:28 来源:https://blog.csdn.net/Z102704/article/details/141827815  浏览:    关键词:C++基础知识

1、基本概念

1.1 引用类型(reference)

         对一个数据可以使用" 引用 " reference )类型,这是 C++ C 的一个重要扩充,引用是一种新的变量类型,它的作用是为一个变量起一个别名
int a; int &b = a;
        在声明变量 b 时变量 a 的引用后,在它们所在函数执行期间,该引用类型变量 b 始终与其代表的变量 a 相联系,不能再作为其他变量的引用( 别用 ) ,意思是 " 企图使 b 又变成其他变量的引用是不行的 "
        C++之所以增加引用类型,主要是把它作为函数参数,以扩充函数传递数据的功能。指针变量要另外开辟内存单元,其内容是地址,而引用变量不是一个独立的变量,不单独占内存单元。这种传递方式比使用指针比变量简单、直观、方便。使用变量的引用,可以代替部分指针的操作。引用不仅可以用于变量,也可以用于对象。
示例代码:
#include <iostream>
using namespace std;//typedef //类型重定义
/*C语言使用指针存储变量的地址 可以由指针对变量操作C++语言弱化指针的概念,引入了 引用 的概念格式:类型 &引用变量名 = 需要引用的变量[C语言中的空指针NULL C++中空指针nullptr]*/
void exchange(int &x, int &y);
int main()
{/*int a = 10;int *p = &a;        //int*类型的指针p指向int类型变量*p = 50;            //将a改为50int &b = a;cout << b << endl;  //引用就是给变量起别名,引用必须和要引用的变量是同类型char m = 'A';char &n = m;cout << n << endl;  //通过引用也可以修改原有变量的内容n = 'a';cout << n << endl;*/int a = 10;int b = 40;int &c = a;//c = b;          //引用无法修改指向exchange(a, b);cout << a << "  " <<b << endl;return 0;
}/* 引用的产生主要是为了函数传参(传参类的对象) */
void exchange(int &x, int &y){int temp = 0;temp = x;x = y;y = temp;
}
/*引用 和 指针的区别1. 指针是一个变量,占8字节(64系统),系统会为其分配至地址引用不是变量,不占空间,只是原本变量的别名2. 指针可以修改指向,但是引用一旦定义就无法修改指向,因为依赖于变量存在3. 指针定义的时候可以不初始化,但是引用定义的同时必须初始化
*/

 2.2 内置函数(inline-function

        C++提供一种提高效率的方法,即在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去。这种嵌入到主调函数中的函数称为内置函数(inline function ),又称内嵌函数。指定内置函数的方法很简单,只需在函数首行的左端加一个关键字 inline 即可。
        内置函数中不能包括复杂的控制语句,如循环语句和 switch 语句。
        应当说明:对函数作 inline 声明,只是程序设计者对编译系统提出的一个建议,也就是说它是建议性的,而不是指令性的。并非一经指定为 inline ,编译系统就必须这样做。编译系统会根据具体情况决定是否这样做,例如对前面提到的包含循环语句和 switch 语句的函数或一个递归函数是无法进行代码置换的,又如一个 1000 行的函数,也不大可能在调用点展开。此时编译系统就会忽略 inline 声明,而按普通函数处理。
        总结,只有那些规模较小而又被频繁调用的简单函数,才适合于声明为内置函数。
示例代码:
#include <iostream>
using namespace std;/*内置函数 / 内联函数 / 内嵌函数称以下体积较小并且逻辑简单,调用次数较多的函数为内置函数如果函数体内部逻辑复杂,while,for,if等判断循环分支语句都不建议设置为内置函数格式:在函数名称前加上关键字inline[加上关键字知识给编译器提建议,具体是否将函数设置为内置函数还是要看编译器的判断结果][如果函数过于复杂,编译器将函数看作普通函数对待]
*//*如果在程序中要重复多次的执行简单动作,例如函数
跳转时间 1ms
函数执行时间 0.5ms
函数如果在程序中调用100次 跳转时间一共就100ms
如果函数体转换时间花费较多可以将函数设置为内联函数实现过程:将实参传给形参,将形参拷贝到函数体内部再将函数体内部执行程序替换到主程序中调用该函数的位置*/
inline void printInfo(string name, int id){cout << name << "  " << id << endl; 
}int main(){printInfo("A", 1000);printInfo("B", 1001);printInfo("C", 1002);cout << "D" << "  " << 1003 << endl; //....return 0;

2.3函数重载(function-overloading

        C++允许用同一个函数名定义多个函数,这些函数的参数个数和参数类型不同,这就是函数的重载。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。
        重载函数除了允许参数类型不同以外,还允许参数的个数不同。

2.4函数模板(function-template)

        C++提供了函数模板。所谓的函数模板,实际上是建立一个通用函数,其函数类型和参数类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板,凡是函数体相同的函数都可以用这个模板来代替,不必定 义多个函数,只需再模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。
通用类型定义 
template <typename XXX> 
template 的含义是"模板",
<>中先写关键字 typename 或 class ,后边跟一个类型参数 
XXX,类似标识符, 是一个虚拟的类型名

2.5 动态内存分配

        在软件开发的过程中,常常需要动态地分配和撤销内存空间、例如对动态链表中节点的插入和删除。C 语言中 是利用库函数 malloc free 来分配和撤销内存空间的,而 C++ 则提供了较为简便且功能较强的运算符 new 和 delete 来取代 malloc free 函数。
         需要注意的是,new 和 delete 是运算符,不是函数,因此执行效率更高。为了与 C 语言兼容,C++仍保留了malloc 和 free 函数,但不建议使用,更推荐使用 new 和 delete
/* 开辟一个存放整型的存储空间,返回一个指向该存储空间的地址(指针) */ 
int *p = new int; 
/* 开辟一个存放整型的存储空间,并指定该整数的初值为 100 */ 
int *p = new int(100); 
/* 开辟一个存放二维整型数组的空间,返回首元素的地址 */ 
int (*p)[4] = new int[5][4]; 
new 运算符使用的一般格式为:new 类型(初值) 用 new 分配数组空间时不能指定初值。 
如果由于内存不足等原因而无法正常分配空间,则 new 会返回一个空指针 NULL,用户可以根据该指针的值判 断分配空间是否成功。 delete 运算符使用的一般格式为:delete []指针变量 对基本数据类型的申请可以直接释放。 
如果是类似"char *pt = new char[10]"申请的字符数组空间(构造数据类型空间),释放时应在指针变量前 加一对方括号,表示是对数组空间的操作:delete []pt;
#include <iostream>
using namespace std;/*C语言中使用malloc free进行堆区空间的申请和释放void * malloc()C++ 使用new delete
*/typedef struct Person{string name;int age;
}P_t;
int main(){int *p = new int;	//申请4字节空间int *q = new int(50);	//申请4字节空空间的同时初始化*p = 100;cout << *p << endl;		//100cout << *q << endl;		//50int *t = new int[10];	//申请10个连续的4字节空间for(int i=0; i<10;i++){	//循环初始化*(t+i) = i;}for(int i=0; i<10;i++){cout << *(t+i) << endl;}int *T = new int[5]{8,5,2,3,0};	//申请同时初始化for(int i=0; i<5;i++){cout << *(T+i) << endl;}struct Person *L = new P_t{("Zhang"), 90};delete p;delete q;delete []t;           //动态申请的连续空间在释放时要加上[]delete []T;delete L;return 0;
}

2、概念升级

2.1 类的定义和使用

        定义类需要使用关键字 class ,然后指定类的名称。类的主体是包含在一对花括号中,其中包含成员变量和成员函数。定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
class 类名 
{访问修饰符: // 
属性 type name; // 
方法 type method(); };
// 和结构体类型定义相同 类的定义需要以分号结尾
        类用来创建对象,对象中的数据成员可以使用运算符"." 进行访问,类不仅可以创建对象变量,也可以创建对象指针,对象指针访问数据成员则使用运算符" -> " ,这一点和结构体类似。
示例代码:
#include <iostream>
using namespace std;
/** 在C语言结构体中不能定义或者实现函数,在c++中结构体可以* 在类中也可以直接定义以及实现函数*  类  class*  类中的内容:分为两种变量(属性)和函数(方法)*  定义类的格式:*      class 类名{*          //类中的成员函数以及成员变量*      }**  类中成员有三种访问修饰符 public protected private*  public:公开成员,类内类外都可以访问*  protected: 保护成员,类内可以访问,类外不能访问,但是继承类可以访问*  private:私有成员,类外不可访问,继承类也不能,友元类和友元函数可以访问**  类中如果没有任何访问修饰符,那么全部成员是私有的*/
class myclass{
public:string name;int age;friend void friendFunc();           //声明友元函数,此类中的私有成员在友元函数种可以访问问friend class fclass;void inputInfo(string t_name, int t_age){name = t_name;age = t_age;}void ouptInfo(){cout << "name=" + name << "  " << "age=" << age <<endl;}
private:int private_num;
};void friendFunc(){myclass user2;user2.private_num = 100;   //在友元函数种访问私有成员
}int main()
{//使用自定义的类定义对象 -- 实例化类myclass user;//调用成员函数对成员变量赋值user.inputInfo("Zhang", 20);user.ouptInfo();return 0;
}

2.2构造函数/析构函数

myclass.h:

#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
using namespace std;
/** 构造函数和析构函数由系统生成并调用,不由用户调用*  构造函数在对象生命周期开始的时候被调用*  析构函数在生命周期结束时候被调用*/class myclass{
public://无参构造函数-默认myclass();             //构造函数函数名和类名相同,没有返回值,可以传参数,可以被重载~myclass();            //构造函数函数名是类名加上~,没有返回值,不可以传参数,不可以被重载//如果在类内显式声明构造函数就要实现myclass(string name, int age);              //构造函数重载myclass(string name, int age, char sex);    //构造函数重载myclass(const myclass &obj);                //拷贝构造函数-将另外一个对象的全部内容拷贝给当前的对象//编译器也会自动生成拷贝构造函数可以直接使用void outputInfo(){              //该函数为公开函数,可以在类外访问该函数,间接访问或者修改私有成员cout << name << endl;cout << age << endl;cout << sex <<endl;//this->name; //在普通成员函数内可以使用this}static int num;     //静态成员变量static void static_func(){//cout << this << endl;     //静态成员函数中不能使用thiscout << "staic func " << endl;}protected:
private:		//私有成员 类外无法访问 [友元函数可以]string name = "Zhang";int age;char sex;
};#endif // MYCLASS_H

myclass.cpp:

#include "myclass.h"myclass::myclass(){cout << "无参构造函数:" << name <<"生命周期开始" <<  endl;
}myclass::~myclass(){cout << "析构函数:" << name <<"生命周期结束" <<  endl;
}//构造函数重载
myclass::myclass(string name, int age){this->name = name;              //在函数体内部初始化成员变量this->age = age;cout << "有参构造函数:" << name <<"生命周期开始" <<  endl;
}
//this指针:只能在类内的成员函数中使用,指向调用成员函数的对象,是一个无类型的指针(静态成员函数中不能用this指针)//构造函数重载--形参初始化列表  -> 要初始化的成员名称(形参) 以逗号分隔开
myclass::myclass(string name, int age, char t_sex) : name(name), age(age), sex(t_sex){cout << "有参构造函数:" << name <<"生命周期开始" <<  endl;
}//拷贝构造函数 自定义并实现
myclass::myclass(const myclass &obj){name = obj.name;age = obj.age;sex = obj.sex;
}

main.cpp:

#include "myclass.h"//在c++源文件种,可以定义结构体在结构体定义并实现函数
//结构体种的函数默认的访问修饰符public
//也可以使用其他两个修饰符//结构体类型    变量
//类 (数据类型) 对象(变量)int myclass::num = 80;			//静态成员函数必须在类外部定义一次int main()
{
/*myclass u1;             //对象的生命周期开始myclass u2("Wang", 50); //有参构造函数--重载u2.outputInfo();myclass u3("Liu", 10, 'm');  //有参构造函数--重载u3.outputInfo();myclass u4(u3);         //拷贝 构造函数u4.outputInfo();
*/myclass user;myclass::static_func();         //静态成员变量以及静态成员函数访问方式//1. 使用类定义对象,通过对象进行访问//2. 直接使用类加上访问限定符访问静态成员(变量/函数)cout << myclass::num++ << endl; //80cout << myclass::num++ << endl; //81cout << myclass::num << endl;   //82return 0;
}

2.3继承/抽象类/虚函数/多态

#include <iostream>
using namespace std;/* 基类 父类 */
class Parent{
public:                 //类内外string name;Parent(){cout << "父类的无参构造函数" << endl;}Parent(int num){this->private_num = num;cout << "父类的构造函数重载" << endl;}void outputInfo(){cout << name << endl;cout << age << endl;}virtual void buy(){cout << "父类 全价" << endl;}protected:          //只能在类内访问和派生类中访问int age;private:            //只能在类内访问 和 友元函数内int private_num;
};/* 派生类 子类 */
//格式 class 类名 : 继承方式 父类名称{}
class Child : public Parent{//默认存在基类中公开的成员//可以再定义一些派生类的成员
public:Child(){cout << "子类的无参构造函数" << endl;}virtual void buy(){         //覆盖  override重写cout << "子类 半价" << endl;}
};class abclass{
public:virtual void abfunc() = 0;            //纯虚函数  含有纯虚函数的类叫做抽象类-无法实例化的类
};//如果继承自抽象类的派生类不重写基类中的纯虚函数,那么派生类也是抽象类,无法实例化
class son_abclass: public abclass{          //抽象类的派生类
public:virtual void abfunc() override{cout << "这是派生类的重写" << endl;}
};void func(Parent &p){p.buy();
}//多态:不同对象调用同一接口时有不同的动作
int main()
{//使用派生类定义对象  可以直接访问基类中的公开成员//Child child1;
/*Parent p1;      //基类对象Child c1;       //派生类对象Parent *P;P = &p1;P->buy();		//如果基类和派生类没有加上virtual,那么此处和79行P->buy()都会调用基类中的buy函数P = &c1;P->buy();		//如果在基类以及子类中的成员函数都没有使用virtual进行修饰==没有满足多态//那么调用函数时会根据指针的类型调用,也就是说基类的指针指向子类成员(此时指针类型为基类)//也会调用基类中的成员函数而不是派生类的成员函数
*//*Parent p1;      //基类对象Child c1;       //派生类对象func(p1);func(c1);*/return 0;
}

(仅供参考学习)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词