C++笔记

一、C语言转型C++

1、C—>C++

//C类型
typedef	struct STASH
{
	int size;			//每个内存块大小
	int quantity;		//存储空间数
	int next;			//下一个空的空间
	unsigned char *storage;	//存储器
}Stash;
void InitStash(Stash *s, int size);
void CleanStash(Stash *s);
int Add(Stash *s, int element);
void* fetch(Stash *s, int index);
int count(Stash *s);
void inflate(Stash *s, int increase);
//C++类型
struct Stash_Cpp    //C++添加成员函数不增加结构体的空间大小,只计算变量的大小总和
{
	int size;			//每个内存块大小
	int quantity;		//存储空间数
	int next;			//下一个空的空间
	unsigned char *storage;	//存储器

	void InitStash( int size);
	void CleanStash();
	int Add(int element);
	void* fetch(int index);
	int count();
	void inflate(int increase);
};

特点:将函数和数据类型集合在一个结构体内,形成一个新的数据类型,称为抽象数据类型,这种类型创建的变量称为这个类型的对象或实例,用对象调用成员函数就是向对象发消息。故面向对象的设计主要活动就是向对象发消息。
结构格式:
class(struct) 类名
{
public: //共有类
protected: //保护类
private: //私有类
//成员属性
//成员函数
};
实例化对象:类名 a; //a 就是实例化对象
2、边界限定
因C语言对结构体的数据处理是没有边界限定的,C++引进了边界概念,让数据更加安全操作。所以引进三个关键字:public、private、protected。
2.1、public 同C语言的struct功能,对所有成员都可以取用,对外不做限制。
2.2、private 类的内部成员函数调用。不能通过类的实例变量访问,但可以通过友元类和友元函数访问。
2.3、protected 和private基本类似,只有一点不同:继承的结构可以访问protected,不能访问private。
3、初始化和清除
3.1、通过构造函数初始化每个对象。如果类已经有构造函数,编译器创建对象时自动调用构造函数。命名规则:和类名字相同,没有返回值。
3.2、用析构函数确保清除。如果类存在析构函数,编译器会在对象销毁的时候自动调用析构函数。命名规则:和类名称相同,没有返回值和参数。在前面添加 ~。
3.3、缺省构造函数: 当类中不存在显示构造函数,就会产生缺省构造函数。存在构造函数,不存在缺省构造函数。

//构造函数和析构函数实现案例
class X
{
	public:
	X();		//构造函数
	X(int i);	//另一个构造函数
	~X();		//析构函数
};
//当对象超过其定义范围,自动调用析构函数,案例如下
{
	tree t(12);		//这里调用构造函数
}	//括号退出调用析构函数
//外面访问不到t变量

//构造集合初始化,以上面X类进行初始化
X X2[] = {X(1), X(2), X(3)};//定义三个X实例对象的集合(数组)

4、函数的重载
4.1、同样的名字,不同的参数。可以重载

//编译器会分解范围、名字、参数产生内部名称
	void print(char);
	void print(float);
//假设上述两个函数都是全局函数,即确定其范围,加上名称和参数	
//编译器会产生内部名称 _print_char和_print_float这两个内部名称,可以进行重载

4.2、不能通过返回值进行重载
4.3、缺省函数不能重载

int fun1(int a, int b = 1){return a+b;}
int fun1(int a){return a;}
int a;
fun1(a);
//编译器报错,参数列表匹配,这两个不是重载函数	
//缺省函数特点1、只有参数列表后的才参数才能缺省2、一旦使用缺省参数,这个参数后面的参数都应该缺省。
int fun1(int X, int a=1, int b=1, int c=1);	//正确
int fun1(int X, int a=1, int b, int c=1);//错误

5、常量

5.1、使用const限定定义常量。常量只能被定义的时候初始化,在其他地方不能被赋值,即不能当做左操作数。
 特性:c++编译器不会为const分配存储空间,把定义保存在符号表内部,如果强制加extern和取const地址,会为其分配存储空间。
 建议:一个值在其声明周期内不会改变,应将其设为常量,这样程序更安全可靠
//常量案例
int main()
{
	const int i = 10;//常量
	i = 100;	//失败,常量不能修改值
	const int j = i+10;	//常量可以当做右值,
}

5.2、const在指针的应用

//指向const的指针,读法:从标识符开始的地方从里向外读,
//1、const int *pInt;	//读法:pInt是一个指针,他指向const int,这里表明pInt可以指向任何地方,但他指向的内容是不能被改变的
//1.1、int const *pInt;	//读法:pInt是一个指针,他指向const 的int类型,和前面用法一样,为了程序可读性,应采用第一种。
//2、int d = 1; int* const pInt = &d;//读法:pInt是一个指针,指向int类型的const指针。表明这是常指针,初始化后,就只能指向初始化的地址,不能指向其他地址,但可以改变指向地址的值,
int d = 1; 
int* const pInt = &d;	
*pInt = 2; //正确,可以修改d的值。
int dtemp = 1;
pInt = &dtemp;	//错误,常指针不能指向其他地址
const int* const pInt = &d;	//常指针,指向int类型的const指针,不能通过指针修改指向的值
//3、强制类型转化会打破const的安全性
const int e = 10;
int *pInt = (int*)&e;	//有效,但是这样是没意义的。	
//4、常字符串
char *pChar = "ccpoy";	//指针指向常字符串,通过指针修改常字符串,程序崩溃

5.3、const在函数的应用

void t(int *pInt)	
{

}
void u(const int*pcInt)//const修饰参数
{
	//*pcInt = 2;	//不能常量赋值
	int i = *pcInt;
	//int *pInt =  pcInt;//不能用非const指针指向常指针
}
const char* v()	//返回值是const指针
{
	return "this return result is const function\n";
}
const int* const w()//返回值是const并且函数也是const
{
	static int i;
	return &i;
}
int main(int argc, char *argv[])
{
	int x = 0;
	int *pInt = &x;
	const int* pcInt = &x;
	t(pInt);
	//t(pcInt);	//const指针不能传递非const
	u(pInt);
	u(pcInt);
	//char *pChar = v();	//返回值const不能给非const
	const char*pcChar = v();

	//int *pInt2 = w();//返回值const不能给非const
	const int* const pcInt2 = w();
	const int* pcInt22 = w();
	//*w() = 1;//const类型值不能做为左值
	system("pause");
	return 0;
}

5.4、const在类的应用

//定义const类对象,同定义普通数据类型一样,const对象只能调用const函数和const成员变量
const int i = 1;	//普通类型
const blok B(2);	//类类型
//定义类的成员函数,在函数体后加const
//如果在const函数内修改非const变量的值,需要加mutable
class X
{
	public:
		int f()  const;	//声明const成员函数 
		int ff();		//声明非const成员函数
		X(int I);		//构造函数
	private:
		int i;
		mutable int j;
};
X:X(int I) : i(I)	//构造函数初始化参数表
{
}
int X::f() const	//const成员函数的定义,
{
	//i = 1;	//错误,通过常量对象访问const函数,进而访问非const的i
	j = 1;	//ok  mutable声明的变量可以在const函数进行修改
	return i;
}
int X::ff()
{
	i = 1;	//ok
	j = 1;	//ok
	return i;
}
int main()
{
	X* x = new X();
	x->f();		//ok 因为const成员函数内部不允许进行修改,所以可以用非const对象调用,用于获取成员变量的信息,
	x->ff();	//ok
	const X*ac = new X();
	ac->f();	//ok
	//ac->ff(); 	//not ok   const对象只能访问const成员函数
}

5.5、volatile关键字
在编译器认知范围内,这个数据是可以改变的。如果编译器把数据读到寄存器内,并且和寄存器没有任何接触,一般不会读取这个数据并进行优化。加上volatile修饰,告诉编译器不能做这样的假设,因为可能被其他进程改变,就必须要读取该数据并不能优化。
注意:volatile的修饰的成员函数,只能通过volatile对象进行调用。

6、内联函数

	定义:在类内定义的函数自动是内联函数,或者加 inline关键字放在类外定义的函数成为内联函数。
class X
{
	public:
		int f() {return i;}	//内联函数
		inline int ff();	//内联函数
	private: 
		int i;
};
 inline int X::ff()
{
	return i;
}
//可以将将内联函数设计成存取器和修改器,这样可以快速节省开销
class Rectangle
{
public:
	Rectangle(int W = 0, int H = 0) : Width(W), Heigth(H) {}	//初始化列表
	int Width() const {return width;}	//read	存取器
	int Width(int W) {width = W;}		//set  修改器
	int Heigth() const {return heigth;}	//read  存取器
	int Heigth(int H) {heigth = H;}		//set   修改器
private:
	int width, heigth;
};

7、命名控制

7.1、static关键字
一般情况下,在文件范围内定义的名字在所有编译单元是可见的。这就是外部链接,全局变量和普通函数都有外部链接的。所以是可见的。
需求:现在想控制名字的可见性,变量在该文件范围内是可见的,可以使用本文件的所有函数都可以使用它。但是在其他文件是不能看见和使用的,即只能在本文件内部使用,这里就要使用static关键字。

int a=0;//其中a是存储在静态数据区,对所有的编译单元都是可见的。   
static int a=0;	//a 还是存储在静态数据区,限定在本编译单元可见,即当前Cpp。
void f()
{
	static a = 0;//不会改变变量的可见性,该变量只能在本函数使用,会改变变量的存储类型,将栈区存储改变成静态数据区存储
}

7.2、其他关键字
extern:改变变量供外部编译单元访问。
auto:设置变量为局部变量,几乎不用,编译器会根据上下文判断其为局部变量。
register:也是局部变量,告诉编译器将其保存在寄存器里面,因为编译器优化比我们做的好,应避免使用。
7.3、静态成员变量和静态成员函数

class X
{
public:
	X(int I=0) : i(I){j=i;}
	int value() const {return i;}
	static int add()
	{
		 //i++;	//错误,静态成员函数不能调用非静态成员变量
		 return ++j;  //调用静态成员变量
	}	
	static int f()
	{
		//value();	//错误静态成员函数不能调用非静态成员函数
		return add();//调用静态成员函数
	}
	int i;
	static int j;
};
int X::j = 0;	//类内的静态成员变量初始化

int main()
{
	int ret;
	X x;
	X *px = &x;
	ret = x.j;
	ret = px->j;
	ret = X::j;
	
	ret = x.i;
	ret = px->i;
	//ret = X::i;//非静态成员变量不能通过类名调用
	
	x.value();
	px->value();
	//X::value();//非静态成员函数不能通过类名调用
	
	x.f();
	px->f();
	X::f();
	return 0;
}


说明:
1、静态成员和静态成员函数都可以被类对象调用或者通过类名::调用。
2、非静态成员和非静态成员函数不能通过类名::调用,可以通过类对象调用。
3、静态成员函数只能调用静态成员变量,不能调用非静态成员变量。
7.4、C++链接C库函数

#ifndef _DISPLAYPOS_H_	//条件编译,防止重复定义  其中#ifndef/#ifdef和#endif成对存在
	#define _DISPLAYPOS_H_

#ifdef __cplusplus
extern "C"{		//C++编译器连接C库函数
#endif //对应#ifdef __cplusplus
		//c库函数的声明
#ifdef __cplusplus
}
#endif	//对应#ifdef __cplusplus
#endif	//对应上面 #ifndef _DISPLAYPOS_H_

8、引用和拷贝构造函数

//C和C++指针针对void*的区别
int *pi;
float *pf;
void *v;
v = pi;		
v = pf;   //C中可以编译通过,但是C++会提示错误。
//引用的示例
int x;
int &px = x;	//创建引用px指向int类型变量
int & g(int &px)	//函数的参数个返回值的引用
{
	px++;
	return px;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值