C++基础知识

专业术语

1 #ifndef

#ifndef起到的效果是防止一个源文件多次包含同一个头文件
#ifndef _HEADFILE_1_H
#define _HEADFILE_1_H
如果没有定义的话,那我定义一下。
在调试程序时,常常需要对程序中的内容进行选择性地编译,即可以根据一定的条件选择是否编译。

#ifndef 标识符

程序段 1

#else

程序段 2

#endif

它的作用是当“标识符”没有由#define定义过,则编译“程序段1”,否则编译“程序段2”。

2 cstddef头文件

内定义了常用的常量、宏、类型和函数

NULL : 指针值用来表示未定义或无值
nullptr_t : nullptr的类型
size_t : unsigned int,用来表示大小(比如元素的个数)
ptrdiff_t : int,用来表示指针之间的距离
max_align_t:所有环境之最大齐位所对应的类型
offsetof(type,mem):表示成员mem在某个struct或union中的偏移量

3 cstdlib头文件

C++ cstdlib 是原始 <stdlib.h> 的 C++ 增强版。

C 标准库头文件 <stdlib.h> 为 C 语言程序员提供可靠、高效的函数,以实现动态内存分配、数据类型转换、伪随机数生成、过程控制、搜索和排序、数学以及多字节或宽字符函数。除了这些常见例程外,还包括一些常用常数,以促进组织和平台间的代码标准化。
abs()
div 除以整数得出商,返回余数结果
atoi 将一个字符串转换成一个整数
atof 转换为双精度浮点型
atol 转换成长整数
rand 生成一个伪随机数
srand 设置随机数生成器的种子值
malloc 、free
bsearch 对数组进行二进制搜索
qsort 采用快速排序

exit() 关闭所有文件,终止正在执行的进程。
return与exit()的区别
在最初调用的main()中使用return和exit()的效果相同。
如果main()在一个递归程序中,exit()仍然会终止程序;但return将
控制权移交给递归的前一级,直到最初的那一级,此时return才会终止程序。return和exit()的另一个区别在于,即使在除main()之外的函数中调用exit(),它也将终止程序。

4 climits头文件

climits定义了符号常量来表示类型的限制
UINT_MAX unsigned int的最大值

5 iostream头文件

iostream 库的基础是两种命名为 istream 和 ostream 的类型,分别表示输入流和输出流。流是指要从某种 IO 设备上读出或写入的字符序列。

6 explicit

指定一个函数只能显示的转换,不能隐式转换。

explict operator int()
{
cout<<"convert to int"<<endl;
}
explict operator double()
{
cout<<"convert to double"<<endl;
}
int main(){
Class a;  
cout<<a<<endl;   
cout<<(double)a<<endl; //要不然会出现歧义;
}

7 operator

7.1 operator作类的转换函数

类可以使用构造函数将其他类型转化为此类的对象,比如

my_class a = my_class(int i);

同样,也可以使用类的转换函数将类的对象转化为其他的类型。
类的转换函数应当满足以下的几个条件:

转换函数必须是类方法
转换函数不能指定返回类型
转换函数不能有参数

#include <iostream>
using namespace std;
class my_class
{
public:
    operator int()//定义了一个将类转化为int的转换函数
    {
        cout << "convert_to_int" << endl;
        return 1;
    }
};
int main()
{
    my_class a;
    int i_a = (int)a;//第一次显式的转换
    cout << a << endl;//第二次隐式的转换
    return 0;
}

7.2 operator在类中重载运算符

类型转换:operator <类型>()
运算符重载:<类型> operator <运算符>(<参数表>)
运算符重载,运算符用法不变,操作的内容变成了我们自定义的数据类型(比如class)
运算符重载实现为类的成员函数,非类的成员函数(全局函数)

#include <iostream>
 
using namespace std;
 
class person
{
private:
    int age;
public:
    person(int nAge)
    {
        this->age = nAge;
    }
 
    bool operator==(const person& ps)
    {
        if (this->age == ps.age)
        {
            return true;
        }
        return false;
    }
};
 
int main()
{
    person p1(10);
    person p2(10);
    
    if (p1 == p2)
    {
        cout << "p1 is equal with p2." << endl;
 
    }
    else
    {
        cout << "p1 is not equal with p2." << endl;
    }
    
    return 0;
}

因为运算符重载函数“operator==”是 person 类的一个成员函数,所以对象 p1、p2 都可以调用该函数。其中的 if (p1 == p2) 语句,相当于对象 p1 调用函数“operator==”,把对象 p2 作为一个参数传递给该函数,从而实现了两个对象的比较。

运算符重载实现为非类的成员函数(即全局函数)
对于全局重载运算符,代表左操作数的参数必须被显式指定。

// 左操作数的类型必须被显式指定
// 此处指定的类型为person类
bool operator==(person const& p1 ,person const& p2)
{
    if (p1.age == p2.age)
    {
        return true;
    }
    else
    {
        return false;
    }
}

可以根据以下因素,确定把一个运算符重载为类的成员函数还是全局函数:

  • 如果一个重载运算符是类的成员函数,那么只有当与它一起使用的左操作数是该类的对象时,该运算符才会被调用;而如果该运算符的左操作数确定为其他的类型,则运算符必须被重载为全局函数;
  • C++ 要求’=‘、’[]‘、’()‘、’->'运算符必须被定义为类的成员函数,把这些运算符通过全局函数进行重载时会出现编译错误;
  • 如果有一个操作数是类类型(如 string 类),那么对于对称操作符(比如操作符“==”),最好通过全局函数的方式进行重载。

实现运算符重载时,需要注意以下几点:

重载后运算符的操作数至少有一个是用户定义的类型;
不能违反运算符原来的语法规则;
不能创建新的运算符;
有一些运算符是不能重载的,如“sizeof”;
=、()、[]、-> 操作符只能被类的成员函数重载。

#include<iostream>
class Myclass{
p
rivate: int a_, double b_;
public:
Myclass(int a, double b):a_(a), b_(b){}
~Myclass{}
int get_a() { return a_;}
double get_b() { return b_;}
 Myclass operator+(const Myclass & adder) const{
 	Myclass sum;
 	sum.a = a_ + adder.a_;
 	sum.b = b_ + adder.b_;
 	return sum;
 	}
 	friend Myclass operator-(const Myclass & A, const Myclass &B)
 	{
 	Myclass diff;
 	diff.a = A.a_ - B.a_;
 	diff.b = A.b_ - B.b_;
 	return diff;
}
};
int main()
{
	Myclass A(1, 1.1);
	Myclass B(2, 2.2);
	Myclass sum = A + B;
	Myclass diff = A - B;
	cout<<sum.get_a() << "\t" << sum.get_b() <<endl;
	cout<<diff.get_a() << "\t" << diff.get_b() << endl;
    return 0;
}

不能重载的运算符: sizeof,
. : 成员运算符
.* : 成员指针运算符
:: : 作用域解析运算符
?: :条件运算符
const_cast:强制类型转换运算符
dynamic_cast:强制类型转换运算符
reinterpret_cast:强制类型转换运算符
static_cast:强制类型转换运算符

只能通过成员函数重载:
=:赋值运算符
():函数调用运算符
[]:下标运算符
->:通过指针访问类成员的运算符
可重载的运算符: + - * / % ^ & | ~= ! = < > += -= = /= %= ^= &= << >> >>= <<= == != <= >= && || ++ – -> -> () [] new delete new[] delete[]

函数调用运算符重载,operator() ,仿函数

8 友元函数

友元的目的 就是让一个函数或者类 访问另一个类中的私有成员, 在类内做友元的函数声明,就可以使某个全局函数可以访问类内的私有成员。

class Building
{
	// 告诉编译器 laoWang全局函数是 Building类  的好朋友,可以访问	Building对象的私有成员
	friend void laoWang1(Building *building);
	private:

	string m_BedRoom;		// 卧室
};
void laoWang1(Building *building)
{
	cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_SittingRoom << endl;

	cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_BedRoom << endl;
}

待补

9 typedef

用新的类型名替换变量名
typedef int myint_t; ———— 在语句开头加上typedef关键字,myint_t就是我们定义的新类型
typedef void (*PFUNA)(int a);

9.1 typedef的作用

定义机器无关的类型,在支持long double的机器上,使用
typedfe long double REAL;
如果在不支持long double的机器上运行相关代码,只需要修改上述语句:
typedef double REAL;

使用 typedef 为现有类型创建别名,给变量定义一个易于记忆且意义明确的新名字。例如:
typedef unsigned int UINT

使用 typedef 简化一些比较复杂的类型声明,例如:

typedef void (*PFunCallBack)(char* pMsg, unsigned int nMsgLen);

上述声明引入了 PFunCallBack 类型作为函数指针的同义字,PFunCallBack 类型定义的指针会指向一个函数,该函数包含两个类型分别为 char* 和 unsigned int 的参数,以及一个类型为 void 的返回值。通常,当函数的参数是一个回调函数时,就可能会使用 typedef 来简化声明。

RedisSubCommand(const string& strKey, PFunCallBack pFunCallback, bool bOnlyOne);

typedef与#define
两者的区别如下

typedef char* pStr1;
#define pStr2 char* 
pStr1 s1, s2;
pStr2 s3, s4;

在上述的变量定义中,s1、s2、s3都被定义为 char* 类型;但是s4则定义成了 char 类型,而不是我们所预期的指针变量 char*,这是因为 #define 只做简单的字符串替换,替换后的相关代码等同于为:

char* s3, s4;

而使用 typedef 为 char* 定义了新类型 pStr1 后,相关代码等同于为:

char *s1, *s2;
typedef char *pStr;
char string[5]="test";
const char *p1=string;
const pStr p2=string;
p1++;
p2++;

还有一个,常量指针中,替换typedef的问题,有点复杂,这里不赘述,
具体参考:https://blog.csdn.net/liitdar/article/details/80069638

10 类模板

11 ::的作用

声明作用域和所属类,或者 前面什么都不加,那就是全局函数

指针占多少内存

在32位操作系统下,指针是占4个字节空间大小,不管是什么数据类型
在64位操作系统下,指针是占8个字节空间大小,不管是什么数据类型

参考文章

  • cstddef: https://blog.csdn.net/qq_44800780/article/details/103530290
  • operator: 《c++ 中 operator
    使用小结》、https://blog.csdn.net/liitdar/article/details/80654324
  • climits: https://blog.csdn.net/benobug/article/details/105092752
  • 友元函数:《C++:友元(看这一篇就够了)》https://blog.csdn.net/weixin_46098577/article/details/116596183

C++类模板:https://blog.csdn.net/professor_tao/article/details/124566910

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值