首页 > 编程语言 >c++关键字学习

c++关键字学习

时间:2023-02-20 15:44:12浏览次数:54  
标签:const 函数 int c++ 学习 关键字 重载 变量

const修饰普通变量

const有以下几个方面的作用:
1)定义const常量,具有不可变性(只读变量)。
2)进行类型检查,使编译器对处理内容有更多了解,消除一些隐患。
3)避免意义模糊的数字出现,同样可以很方便地进行参数检查和修改。同宏定义一样,可以做到不变则已,一变都变。
4)保护被修饰的东西,防止被意外修改,增强了程序的健壮性。
5)为函数重载提供参考。
6)节省空间,避免不必要的内存分配。const定义的常量在程序运行过程中只有一份复制品,而#define定义的常量在内存中有若干个复制品。
7)提高了程序的运行效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,使得它成为一个编译期间的常量,没有了存储和读内存操作,使得它的运行效率也很高。

{	
	// 以常量初始化const修饰的只读变量 那么只读变量的值 事先存放在“符号常量表中” 不会立即给data开辟空间
	const int data = 100; // 常量初始化
	int* p = (int*)&data; // 对data取地址时,才会开辟空间
	*p = 2000;
	cout << " * p = " << *p << endl; // 2000
cout << "data = " << data << endl; // 100
}
{
// 以变量初始化const修饰的只读变量 那么只读变量会立即开辟空间(没有符号常量表)
	int data = 100; 
	const int data2 = data; // 变量初始化
	int* p = (int*)&data2;

	*p = 200;

	cout << "data2 = " << data2 << endl; // 200
cout << "*p = " << *p << endl; // 200
}

register修饰寄存器变量

(能够提高变量访问效率,提升程序运行速度)
如果变量高频繁使用,会自动将变量存储在寄存器中 目的:提高访问效率
使用register关键字修饰,能够将变量直接放入寄存器中

{
// 注意尽量不要对寄存器变量取地址,因为取地址是对内存的操作
register int data = 10;//data放入寄存器中
}

了解一下:register 修饰的变量,只是尽量放入寄存器中


volatile关键字

强制访问内存

防止编译器优化

{
volatile int data = 10;//对data的访问,必须从内存访问
}

大部分对单片机操作,传感器操作

	//sizeof测量类型的大小
{
	cout << "sizeof(int) = " << sizeof(int) << endl; //4
	cout << "sizeof(char) = " << sizeof(char) << endl; //1
	cout << "sizeof(short) = " << sizeof(short) << endl; //2
	cout << "sizeof(long) = " << sizeof(long) << endl; //4
	cout << "sizeof(float) = " << sizeof(float) << endl; //4  32位平台
	cout << "sizeof(double) = " << sizeof(double) << endl; //8
}

typedef 关键字

功能:给已有的类型重新取个变量名

不能创建新的类型。
将长且复杂的类型名 去一个短小的名称。

typedef作用的步骤:
1)先用已有的类型 定义一个普通的变量
2)用别名 替换 变量名
3)在整个表达式最前面 加typedef

{
	typedef int INT32; // INT32就是int类型的别名

	INT32 data;
	int num; // 已有类型仍然有效
}

案例1:给int arr[5]取个别名

{
	typedef int myarr[5];
	myarr arr = { 1,2,3,4,5 };
	for (int i = 0; i < sizeof(myarr) / sizeof(int); i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}

案例2:给int *取个别名

{
	typedef int* myp;
	myp p; //p的类型就是int *类型
}

随机数 函数:rand()

//需要头文件
#include "time.h"
{
	// 设置随机数种子 time(NULL)获取当前时间
	srand(time(NULL));

	// 产生随机数据的函数rand()
	cout << rand() << endl;
}

编译一个c文件需要四个阶段:
预处理 -> 编译 -> 汇编 -> 链接


友元函数的关键字

friend
借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。
在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。友元函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数。

友元函数可以访问当前类中的所有成员,包括 public、protected、private 属性的。
#include <iostream>
using namespace std;

class Student{
public:
    Student(char *name, int age, float score);
public:
    friend void show(Student *pstu); //将show()声明为友元函数
private:
    char *m_name;
    int m_age;
    float m_score;
};

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }

//非成员函数
void show(Student *pstu)
{
    cout<<pstu->m_name<<"的年龄是 "<<pstu->m_age<<",成绩是 "<<pstu->m_score<<endl;
}

int main(){
    Student stu("小明", 15, 90.6);
    show(&stu); //调用友元函数
    Student *pstu = new Student("李磊", 16, 80.5);
    show(pstu); //调用友元函数

    return 0;
}

mutable关键字

mutable 英文中表示,易变的,不定的;性情不定的,而在代码中表示 可变数据成员。
由前面整理的 const详解 知道,由const修饰的成员函数中,不能对成员变量进行修改,因为隐藏的形参是 const 属性的。
而实际开发过程中,我们可能需要对某些成员变量进行修改,就需要用到 mutable。

class constA
{
public:
	constA(int a):m_a(a){}
	void funcA() const { cout << ++m_a << endl; }

	mutable int m_a;
};
int main(int argc, char *argv[])
{
	constA ab(10);
	ab.funcA();

	const constA abc(11);
	abc.funcA();
	abc.m_a = 15;
	abc.funcA();
}

输出

	11
	12
	16

这里可以看到在const的成员函数中,可以对mutable修饰的变量进行修改。 而对于const对象,它的成员变量依然可以进行修改。
总结一句话:一个 可变数据成员,永远不会是const,即使它是const 对象的成员。


函数重载 关键字 operator

(函数重载是一种静态多态)
简单理解:几个函数的名字相同,但其参数不同或者是参数类型不同;大体相同,细节不同。
举例:交换两个数的值,其中包括int、float、char、double等类型。在C语言中必须要用不用的函数名加以区分,这样的代码会带来很多不便,于是在C++中提出了用一个函数名定义多个函数,也就是函数重载。
函数重载的规则:
函数名必须相同、参数列表必须不同(体现在个数、类型、排列顺序等不同上)、函数的返回类型可以相同也可以不相同、仅仅返回类型不同不足以成为函数的重载。
函数重载的作用:重载函数通常用在同一个作用域内,用同一个函数名命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

#include<iostream>
using namespace std;
int Add(int a, int b){
return a + b;
}
double Add(double a, double b){
return a + b;
}
float Add(float a, float b){
return a + b;
}
int main(){
    cout << Add(1,2) << endl;
    cout << Add(3.5, 4.5) <<endl;
    cout << Add(2.22, 3.33) << endl;
return 0;
}

运算符重载

C++中,运算符能够被用户定义,就是说C++能够为运算符提供数据类型的特殊含义,这种能力称为运算符的重载。
作用举例:
(1)在String类的类中重载运算符"+",以便用"+"就可以连接两个字符串.
(2)重载运算符"+",使其作用为点坐标的相加。
代码举例(复数相加):

#include<iostream> 
using namespace std; 
  
class Complex { 
private: 
    int real, imag; 
public: 
    Complex(int r = 0, int i =0)  {real = r;   imag = i;} 
    Complex operator + (Complex const &obj) {      //重载操作
         Complex res; 
         res.real = this->real + obj.real; 
         res.imag = this->imag + obj.imag; 
         return res; 
    } 
    void print() { cout << real << " + i" << imag << endl; } 
}; 
  
int main() 
{ 
    Complex c1(10, 5), c2(2, 4);    //对数据以类的方式处理
    Complex c3 = c1 + c2; 
    c3.print(); 
}

需要注意的是:为了使运算符重载起作用,至少一个操作数必须是用户定义的类对象。

C++共用体union

  • 结构体:所有成员拥有独立空间
  • 共用体:所有成员共享一块空间

共用体关键字:union

共用体的空间 是由最大的成员决定

union Data
{
    char a;
    short b;
    int c;
};

注意:对任何一成员的操作也是对同一空间的操作;
虽然都是对同一空间进行操作,但是操作的大小是由成员自身的大小决定

C++动态空间分配 new & delete

动态空间分配的关键字是new,删除空间是delete
动态分配
1.在程序运行的过程中,根据大小自由分配空间
2.按需分配
3.分配在堆区,一般使用特定的关键字进行分配

new和delete
new申请堆区空间 delete释放空间;

int *p = NULL;
p = new int; // 从堆区申请int类型大小的空间
*p = 100;
cout<<"*p = "<<*p<<endl;//100

//释放空间
delete p;

//new申请空间的同时 初始化空间内容
int *p1 = NULL;
p1 = new int(10);
cout<<"*p1 = "<<*p1<<endl;//10
delete p;

new和delete操作数组空间
new与[]结合表示申请数组空间 delete释放的时候也需要加[];

int *arr = NULL;
arr = new int[5]{10,20,30,40,50}; // 从堆区申请int类型大小的空间

int i = 0;
for(; i<5; i++)
{
    //cout<<arr[i]<<" ";
    cout<<*(arr+i)<<" ";
}
cout<<endl;//1

//如果new有[] 那么delete是也需要[]
delete [] arr;

virtual 关键字

虚函数的定义:虚函数,是指被virtual关键字修饰的 成员函数。
虚成员函数应在类内定义声明,且必须有定义(实现)。注意,在类外定义实现虚成员函数时,不能再加 virtual 关键字。
子类重写 父类的虚函数:函数名、返回值类型、参数类型个数顺序 必须完全一致

多态的条件:有继承、子类重写父类的虚函数,父类指针指向子类空间

如果一个类中的成员函数被virtual修饰,那么这个函数就是虚函数。类就会产生一个虚函数指针(vfptr)指向了一张虚函数表(vftable)。如果这个类没有涉及继承,这时虚函数中记录就是当前虚函数的入口地址。

class Animal
{
public:
	// 虚函数
	virtual void speak(void)
	{
		cout << "动物在说话" << endl;
	}
};

class Animal
{
public:
	// 纯虚函数
	virtual void speak(void) = 0;
};

一旦类中有纯虚函数,那么这个类 就是抽象类。
抽象类 不能实例化 对象。 (Animal ob; 错误)
抽象类 必须被继承 同时 子类必须重写 父类的所有纯虚函数,否则 子类也是抽象类。

抽象类的主要目的 是设计 类的接口

virtual修饰析构函数
虚析构:通过父类指针 释放整个子类空间。
应用场景:一个函数的参数是基类指针,在主调函数 new 分配了内存,需要在被调函数中使用完该对象后 delete


class Animal
{
public:
	// 虚函数
	virtual void speak(void)
	{
		cout << "动物在说话" << endl;
	}
	// 虚析构
	virtual ~Animal()
	{
		cout << "Animal的析构函数" << endl;
	}
};

class Animal
{
public:
	// 纯虚函数
	virtual void speak(void)
	{
		cout << "动物在说话" << endl;
	}
	// 纯虚析构函数 必须在类中声明,在类外实现
	virtual ~Animal() = 0;
};
Animal::~Animal()
{
	cout << "Animal的析构函数" << endl;
}

虚析构和纯虚析构的区别?

虚析构:virtual修饰,有函数体,不会导致父类为抽象类。
纯虚析构:virtual修饰,=0,函数提必须在类外实现,导致父类为抽象类。

标签:const,函数,int,c++,学习,关键字,重载,变量
From: https://www.cnblogs.com/zhu-jing/p/17115861.html

相关文章

  • WPF学习_day1
    WPF绑定数据使⽤Binding对象建⽴绑定,且每个绑定通常具有四个组件:绑定⽬标、⽬标属性、绑定源以及指向要使⽤的源值的路径。第一种绑定方式(在前台绑定):过程:定义一个字典......
  • 第13届蓝桥杯青少年组C++第5题 金箍棒
    解题思路首先猜想最终相等的元素t的范围,最终应为数组中的某个元素。若t小于数组中所有的元素,则此时增大t,那么所有元素变为t的次数将减小,可见t并非最优解;若t大于数组中......
  • 线段树板子C++
    structnode{intl,r,sum,lazy;node*lson,*rson;node(){l=r=sum=lazy=0;lson=rson......
  • 从C到C++
    从C到C++(二)目录从C到C++(二)一、域运算符C++中新增作用域标识符:::二、new、delete运算符new运算符可以用于创建堆空间三、重载四、namemanagling与extern“C”五、带默认......
  • 通信小白基础学习---LTE核心网网元
    以下内容来源于B站up主“捻叶成剑”,如有侵权,请联系本人删除!NAS非接入层  寻呼-别人给你打电话  鉴权-移动设备是否合法   附着-手机注册网络后一直挂着......
  • Linux学习笔记
    第一章:初识Linux1、LinuxLinux是一套免费和自由传播的类UNIX操作系统(类UNIX系统:是指继承UNIX的设计风格演变出来的系统),是基于POSIX和UNIX的多用户、多任务、支持多线程和......
  • MarkDown学习
    标题三级标题四级标题五级标题 字体Hello,World!Hello,World!Hello,World!Hello,World! 引用(>)学习Java 分割线(---)  图片 ![头像](C:\Users\A......
  • 通信小白基础学习---UCI on PUSCH宏观梳理
    以下内容来源于B站up主“捻叶成剑”,如有侵权,请联系本人删除!原视频链接:https://www.bilibili.com/video/BV1U34y1i7We/?spm_id_from=333.999.0.0&vd_source......
  • C、C++、python、java
    C++和Python的区别python是一种脚本语言,是解释执行的,而C++是编译语言,是需要编译后在特定平台运行的。python可以很方便的跨平台,但是效率没有C++高。Python使用缩进来区......
  • MarkDown的学习
    Markdown学习标题用#空格+文字,几级就几个#字体前后两个*为加粗前后一个*为斜体前后三个*为斜体加粗前后两个~为删除线引用前面一个>空格为引用比如这是引用效......