C++基础部分代码

C++ OOP面对对象 this指针
C:各种各样的函数定义 struct
C++:类==》实体的抽象类型
实体(属性,行为)-》ADT(abstract data type)
OOP语言的四大特征是什么?
抽象 封装/隐藏 继承 多态
访问限定符:public公有的 private私有的 protected保护的

#include<iostream>
#include<string>
using namespace std;




#if 0

const int NAME_LEN = 20;
class CGoods
{
public:		//给外部提供公有的成员方法,来访问私有的属性
	//做数据初始化
	void init(const char*name, double price, int amount);
	//打印信息
	void show();
	//给成员变量提供一个getXXX或setXXX的方法,类体内实现的方法,自动初始化inline
	void setName(char *name){ strcpy(_name, name); }
	void setPrice(double price){ _price = price; }
	void setAmount(int amount){ _amount = amount; }

	const char *getName(){ return _name; }
	double getPrice(){ return _price; }
	int getAmount(){ return _amount; }



private:	//属性默认私有的成员变量
	//对象内存大小的时候,对象的内存大小和成员变量有关
	char _name[NAME_LEN];//20-》24
	double _price;//8
	int _amount;//4-》8
	//24+8+8=40字节
};
void CGoods::init(const char*name, double price, int amount)
{
	strcpy(_name, name);
	_price = price;
	_amount = amount;
}
void CGoods::show()
{
	cout << "name:" << _name << endl;
	cout << "prrice:" << _price << endl;
	cout << "amount" << _amount << endl;
}
int main()
{
/*
CGoods可以定义无数的对象,每一个对象都有自己的成员变量,但是它们共享一套成员方法

show()==>怎么知道处理哪个对象的信息?
inti(name,price,amount)==> 怎么知道把信息初始化给哪一个对象?

类的成员方法一经编译,所有的方法参数,都会加一个this指针,接受调用该方法的对象的地址
void setName(this->char *name){};
*/
	CGoods good1;//类实例化了一个对象
	//good._price;//err

	//init(&good1,"面包", 10.1, 20);
	good1.init("面包", 10.1, 20);
	good1.show();
	//show(&good1);

	good1.setAmount(200);
	good1.show();

	CGoods good2;
	good2.init("冰箱",1980,20);
	good2.show();


	//new 的四种用法
	int *p1 = new int(10);
	int *p2 = new (nothrow)(int);
	const int * p3 = new  const int (2);

	//定位new
	int statu = 0;
	int *p4 = new (&statu)int(30);
	cout << "p4:" << *p4 << endl;

	//c和c++的开辟动态内存:new | malloc
	int *a = (int*)malloc( sizeof (int));
	if (a == nullptr)
	{
		return -1;
	}
	free(a);

	int *a1 = (int*)malloc(sizeof(int)* 20);
	free(a1);


	int *b = new int(20);
	delete (b);

	int *b1 = new int[20]();
	delete[]b1;

	//&&专门用来引用右值类型,指令上,可以自动产生临时量
	int &&d = 20;//== const int &d = 20;

	//int &d1 = 10;//--err
	//不能用一个右值引用变量,来引用左值

	int &c = d; //右值引用变量本身是一个左值,只能有左值引用它
	c = 50;
	cout << "c=" << d << endl;

	return 0;

}

/*
构造函数和析构函数
OOP实现一个顺序栈
*/
class SeqStack
{
public:

	//构造函数 SeqStack s1;	SeqStack s2(20)
	SeqStack(int size = 10)	//是可以带参数的,因此可以提供多个构造函数
	{
		cout << this << "SeqStack()"<<endl;
		_pstack = new int[size];
		_top = -1;
		_size = size;
	}
	//自定义构造函数 <=对象的浅拷贝有问题
	SeqStack(const SeqStack &src)
	{
		cout << "SeqStack &src" << endl;
		_pstack = new int[src._size];
		for (int i = 0; i < src._size; i++)
		{
			_pstack[i] = src._pstack[i];
		}
		_top = src._top;
		_size = src._size;
	}

	//析构函数
	~SeqStack()	//是不带参数的,所以析构函数只能有一个
	{
		cout << this << "~SeqStack()"<<endl;
		delete[]_pstack;
		_pstack = nullptr;
	}
	//赋值重载函数 s1 = s1
	void operator=(const SeqStack &src)
	{
		cout << "operator=" << endl;
		//防止自赋值
		if (this == &src)return;

		//需要先释放当前对象占用的资源;
		delete[]_pstack;

		_pstack = new int[src._size];
		for (int i = 0; i < src._size; i++)
		{
			_pstack[i] = src._pstack[i];
		}
		_top = src._top;
		_size = src._size;
	}
	/*void init(int size = 10)
	{
		_pstack = new int[size];
		_top = -1;
		_size = size;
	}
	void release()
	{
		delete[]_pstack;
		_pstack = nullptr;
	}*/
	void push(int val)
	{
		if (full())
			resize();
			_pstack[++_top] = val;
	}
	void pop()
	{
		if (empty())
			return;
		--_top;
	}
	int top()
	{
		return _pstack[_top];
	}
	bool empty(){ return _top == -1; }
	bool full(){ return _top==_size - 1; }

private:
	int *_pstack;//动态开辟数组,存储顺序栈的元素
	int _top;//指向栈顶元素的位置
	int _size;//数组扩容的总大小

	void resize()
	{
		int *ptmp = new int[_size * 2];
		for (int i = 0; i < _size; i++)
		{
			ptmp[i] = _pstack[i];
			//如果拷贝的是对象,对象指向了外部内存,那就出问题了(浅拷贝)
			//memcopy(ptmp,_psatck,sizeof(int)*_size);
		}
		delete[]_pstack;
		_pstack = ptmp;
		_size *= 2;
	}

};
SeqStack gb;//全局构造在程序运行结束析构
int main01()
{
	//当我在堆区开辟内存,默认的析构函数不起作用,就需要自己delete
	SeqStack *ps = new SeqStack(30);
	ps->push(70);
	ps->push(40);
	cout<<ps->top()<<endl;
	delete ps;//先调用ps->~SeqStack()+然后free(ps)

	//1.开辟内存	2.调用构造函数
	SeqStack s;
	//s.init(5);//对象变量初始化操作
	for (int i = 0; i < 15; i++)
	{
		s.push(rand() % 100);
	}
	while (!s.empty())
	{
		cout << s.top() << " ";

		s.pop();
	}
	//s.release();//释放对象成员变量占用的外部堆内存(外部资源)

	SeqStack s2(20);//先进后出(构造析构)
	
	//s2.~SeqStack();//析构函数调用结束后,我们说对象不存在了
	//s2.push(30);//堆内存的非法访问,析构之后不可在访问对象的成员
	
	return 0;
}

/*
this指针 =》类-》很多对象 共享一套成员方法
成员方法,方法的参数都会添加一个this指针

构造函数:
	定义对象时,自动调用的;可以重载的;构造完成,对象产生了
析构函数:
	不带参数,不能重载,只有一个析构函数;析构完成,对象就不存在了


16.深拷贝和浅拷贝
对象默认的拷贝构造是做内存的数据拷贝
关键是对象如果占用外部的内存,那么浅拷贝就出现问题了!

*/
int main()
{

	SeqStack s;//没有提供任何构造函数的时候,会为你生成默认构造函数和默认析构函数
	SeqStack s1(10);
	SeqStack s2 = s1;//#1	默认拷贝构造函数,做直接内存数据拷贝
	//SeqStack s3(s1);//#2	

	//s2.operator=(s1);
	s1 = s1;


	return 0;
}

#endif
#if 0
/*
17.拷贝构造函数和赋值重载函数应用代码实践

*/
class String
{
public:
	String(const char *str = nullptr)//普通构造函数
	{
		if (str != nullptr)
		{
			m_data = new char[strlen(str) + 1];
			strcpy(this->m_data, str);
		}
		else
		{
			//置为空,让下面的拷贝构造函数不用重新判断是不是有效字符
			m_data = new char[1];
			m_data = '\0';
		}
	}
	String(const String &other)//拷贝构造函数
	{
		m_data = new char[strlen(other.m_data)+1];
		strcpy(m_data, other.m_data);
	}
	~String()
	{
		delete[]m_data;
		m_data = nullptr;
	}
	//String& 是为了连续的operator的操作 s1=s2=s3
	String& operator = (const String &other)//赋值重载函数
	{
		if (this == &other)
		{
			return *this;
		}
		m_data = new char[strlen(other.m_data)+1];
		strcpy(m_data, other.m_data);
		return *this;
	}
private:
	char *m_data;//用于保存字符
};

int main()
{
	String str1;
	String str2("hello");
	String str3 = "world";

	String str4 = str3;
	String str5(str3);

	str3 = str4;
	return 0;
}
#endif
#if 0
//循环队列
class Queue
{
public:
	Queue(int size = 5)
	{
		_pQue = new int[size];
		_front = _rear = 0;
		_size = size;
	}

	//可以限制用户使用拷贝和赋值构造函数
	//Queue(const Queue&) = delete;
	//Queue operator=(const Queue&) = delete;

	Queue(const Queue &src)
	{
		_size = src._size;
		_front = src._front;
		_rear = src._rear;
		_pQue = new int[_size];
		for (int i = _front; i != _rear; i = (i + 1) % _size)
		{
			_pQue[i] = src._pQue[i];
		}
	}
	Queue& operator=(const Queue &src)
	{
		if (this == &src)return *this;

		delete[]_pQue;

		_size = src._size;
		_front = src._front;
		_rear = src._rear;
		_pQue = new int[_size];
		for (int i = _front; i != _rear; i = (i + 1) % _size)
		{
			_pQue[i] = src._pQue[i];
		}
		return *this;
	}
	void push(int val)//入队操作
	{
		if (full())
			resize();
		_pQue[_rear] = val;
		_rear = (_rear + 1) % _size;
	}
	void pop()//出队操作
	{
		if (empty())return;
		_front = (_front + 1) % _size;
	}
	int front()//获取队头元素
	{
		return _pQue[_front];
	}
	bool full(){ return (_rear + 1) % _size == _front;}
	bool empty(){ return _rear == _front; }
	~Queue()
	{
		delete[]_pQue;
		_pQue = nullptr;
	}
private:
	int *_pQue;//申请数组的空间
	int _front;//队头
	int _rear;//队尾
	int _size;//扩容的大小

	void resize()
	{
		int *ptmp = new int[_size * 2];
		int index = 0;
		for (int i = _front; i != _rear; i = (i + 1) % _size)
		{
			ptmp[index++] = _pQue[i];
		}
		delete[]_pQue;
		_pQue = ptmp;
		_front = 0;
		_rear = index;
		_size *= 2;
	}
};
int main()
{
	Queue q1;
	for (int i = 0; i < 20; i++)
	{
		q1.push(rand() % 100);
	}
	while (!q1.empty())
	{
		cout << q1.front() << endl;
		q1.pop();
	}
	Queue q2 = q1;
	q1 = q2;

	return 0;
}
#endif

#if 0
/*
18.构造函数初始化列表	:	可以指定当前对象成员变量的初始化方式
CDate信息 是 CGoods商品信息的一部分 a part of ... 组合关系(继承)
*/
class CDate
{
public:
	CDate(int y, int m ,int d)//自定义了一个构造函数,编译器就不会默认生成构造函数
	{
		_year = y;
		_month = m;
		_day = d;
	}
	void show()
	{
		cout << _year << "/" << _month << "/" << _day  << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

class CGoods
{
public:
	CGoods(const char * n, double p, int a,int y,int m, int d)
		:_date(y,m,d)
		,_amount(a)
		,_price(p)// #1 构造函数的初始化列表
	{

		// #2 当前类类型构造函数体
		strcpy(_name, n);
		//_price = p;
		//_amount = a;
	 

	}
	void show()
	{
		cout << "name:" << _name << endl;
		cout << "price:" << _price << endl;
		cout << "amount:" << _amount << endl;
		_date.show();
	}
private:
	char  _name[20];
	double _price;
	int _amount;
	CDate _date;//成员对象
	
};
int main()
{

	CGoods g1("苹果",9.8,3,2019,3,8);
	g1.show();

	return 0;
}


class Test
{
public:
	Test(int data = 10) :mb(data), ma(mb){}
	void show()
	{
		cout << "ma:" << ma << "mb:" << mb << endl;
	}
private:
	//成员变量的初始化和它们定义的顺序有关,和构造函数列表中出现的先后顺序无关;
	int ma;
	int mb;
};
int main()
{

	Test t1;
	t1.show();
	//ma:-858993460mb:10

	return 0;
}

/*
19.掌握成员方法和区别
普通的成员方法 =》编译器会添加一个this形参变量
1.属于类的作用域
2.调用该方法时,需要依赖一个对象(常对象是无法调用的)
3.可以任意访问对象的私有成员变量 public,private

static静态成员方法 =》不会生成this形惨
1.属于类的作用域
2.用类名作用域来调用方法
3.可以任意访问对象的私有成员,仅限于依赖对象的成员(只能调用其他static静态成员)

const常成员方法 =》const CGoods *this
1.属于类的作用域
2.调用依赖一个对象,普通对象或者常对象都可以
3.可以任意访问对象的私有成员,但是只能读,不可写
*/
class CDate{
public:
	CDate(int y, int m, int d)//自定义了一个构造函数,编译器就不会默认生成构造函数
	{
		_year = y;
		_month = m;
		_day = d;
	}
	void show()const
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

class CGoods
{
public:
	CGoods(const char * n, double p, int a, int y, int m, int d)
		:_date(y, m, d)
		, _amount(a)
		, _price(p)// #1 构造函数的初始化列表
	{

		// #2 当前类类型构造函数体
		strcpy(_name, n);
		_count++;//记录产生新对象的数量
	}
	//普通成员方法
	void show()//打印商品的私有信息 CGoods *this
	{
		cout << "name:" << _name << endl;
		cout << "price:" << _price << endl;
		cout << "amount:" << _amount << endl;
		_date.show();
	}
	//常成员方法:只要是只读操作的成员方法,一律实现成const常成员方法
	void show()const//const CGoods *this
	{
		cout << "name:" << _name << endl;
		cout << "price:" << _price << endl;
		cout << "amount:" << _amount << endl;
		_date.show();
	}
	//静态成员方法 没有this指针的
	static void showCount()//打印的是所有商品共享的信息
	{
		cout << "所有商品种类数量是:" <<_count << endl;
		//cout<<"name:"<<this->_name<<endl;//err
	}
private:
	char  _name[20];
	double _price;
	int _amount;
	CDate _date;//成员对象	1.分配内存 2.调用构造函数

	//int _count;//用来记录商品对象的总数量
	static int _count;//不属于对象,而是属于类级别的  声明

};
//static 成员变量一定要在类外进行定义并初始化
int CGoods::_count = 0;
int main()
{

	CGoods g1("苹果1", 9.8, 3, 2019, 3, 8);
	g1.show();

	CGoods g2("苹果2", 9.8, 3, 2019, 3, 8);
	g2.show();

	CGoods g3("苹果3", 9.8, 3, 2019, 3, 8);
	g3.show();

	CGoods g4("苹果4", 9.8, 3, 2019, 3, 8);
	g4.show();

	//g2.showCount();//4
	CGoods::showCount();
	
	const CGoods g5("非卖品", 6.9, 4, 2022, 4, 6);
	g5.show();

	return 0;
}
#endif
/*
20.指向类成员(成员变量和成员方法)的指针
*/
class Test
{
public:
	void func(){ cout << "call Test::func" << endl;}
	static void static_func(){ cout << "Test::static_func" << endl; }
	int ma;
	static int mb;

private:
};
int Test::mb = 0;
int main()
{
	/*无法从“int”转换为“int Test::*
	int Test::*p = &Test::ma;
	*p = 20;*/

	Test t1;
	Test *t2 = new Test();

#if 0
	int Test::*p = &Test::ma;
	t1.*p = 20;
	cout << t1.*p << endl;//20

	t2->*p = 30;
	cout << t2->*p << endl;//30

	int *p1 = &Test::mb;
	*p1 = 40;
	cout << *p1 << endl;//40
#endif

	//指向成员方法的指针
	/*无法从“void(__thiscall Test::*)(void)”转换为“void(__cdecl *)(void)
	void(*pfunc)() = &Test::func;
	(*pfunc)();*/
	void(Test::*pfunc)() = &Test::func;
	(t1.*pfunc)();
	(t2->*pfunc)();

	//如何定义函数指针指向类的static成员方法呢?
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Choice~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值