C++进阶篇—1

  • 面向对象编程-----------------------------------------------难点
  • 类和对象
  • 类的成员变量
  • 访问修饰符
  • 构造与析构函数----------------------------------------------重点
  • this指针---------------------------------------------------重点

何为面向对象?
所谓面向对象就是基于对象概念,以对象为中心,以类和继承为构造机制,来认识、理解、刻画客观世界和设计、构建相应的软件系统(模拟现实)

1.对象是由数据和容许的操作组成的封装体,与客观实体有直接对应关系

2.面向对象不是某一种语言的特性,而是一种编程思想

抽象

  • 从具体事物抽取共同的本质特征

C++中的类

  • 类是一种将抽象转换为用户定义类型的工具

  • 将数据表示和操纵数据的方法组合成一个整体

  • 类的实例为对象

  • 类中变量和函数称为成员
    在这里插入图片描述
    类的声明

  • 使用**class**/struct关键字声明类型
    在这里插入图片描述
    类的学习
    Land1.h

#pragma once
#include <string>
#include <iostream>


/**
* .hpp文件一般包括实现的内联函数  通常用于模板类这种声明与实现共存的情况
* 建议:只要不是纯模板 一律使用.h作为头文件后缀,使用.cpp文件作为函数的实现文件
*/

using namespace std;

class Land1
{
public:
	string name;  //地主的名称
	long score;		//地主的积分
	int cards[20];		//地主的手牌数组
public:
	Land1();				//构造函数的声明
	~Land1();				//析构函数的声明
	//inline void touchcard(int cardcount)  //默认内联函数
	//{
	//	cout << name << "开始摸牌" << cardcount << "张牌" << endl;
	//}
	//void showscore()
	//{
	//	cout << name << "当前的积分为" << score << endl;
	//}
	void touchcard(int); //声明牌方法
	void showscore(); //声明的显示积分方法

protected:

};

Land1.cpp

#include "Land1.h"


Land1::Land1()   //实现了默认构造函数
{
}


Land1::~Land1()
{
}

//实现摸牌方法
void Land1::touchcard(int cardCount)
{
	cout << name << "开始摸牌" << cardCount << "张牌" << endl;
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件

using namespace std;

int main()
{
	Land1 la1; //声明了一个Land1类型的变量 la1
	//调用对象的成员方法
	int n;
	cin >> n;
	la1.name = "冯是";
	la1.touchcard(n);
	return 0;
}

访问修饰符

常见访问修饰符

  • public:修饰得分成员在任意地方都可以访问
  • pravate:修饰的成员只能够在类中或者友元函数中可以访问
  • protected:修饰的成员可以在类中函数、子类函数及友元函数中访问

修饰成员

将修饰关键字放置在类定义的大括号中,添加冒号
在这里插入图片描述
私有属性怎么修改
Land2.h

#pragma once

#include <string>

using namespace std;

class Land2
{
	//省略了private
	string name;
	long score; //解决积分为负数错误的方法,将成员变量score进行隐藏并封装
	int cards[20];
public:
	

	Land2();
	~Land2();

	void show();

	//使用方法/函数实现对成员变量的封装Get/Set方法
	void SetScore(long lscore)
	{
		if (lscore < 0)
			score = 0;//如果传入的积分是非法情况, 那么积分默认为0;
		else
			score = lscore;//积分为正数时, 才进行赋值操作, 这里就通过条件判断,封装了score的赋值过程
	}
	string GetName();

	void SetName(string na);
};

Land2.cpp

#include "Land2.h"

#include <iostream>

Land2::Land2()
{
}


Land2::~Land2()
{
}

void Land2::show()
{
	cout << name << "得了" << score << "分" << endl;
}

string Land2::GetName()
{
	return name;
}

void Land2::SetName(string na)
{
	name = na;
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件
#include "Land2.h"

using namespace std;

int main()
{
	//Land1 la1; //声明了一个Land1类型的变量 la1
	调用对象的成员方法
	//int n;
	//cin >> n;
	//la1.name = "冯是";
	//la1.touchcard(n);
	//return 0;

	Land2 la2;
	//la2.name = "1231";
	//注意: 模拟为地主修改积分
	//la2.score = 100;  //私有属性,是更改不了的
	la2.SetScore(-100);
	la2.SetName("飞哥");
	cout << la2.GetName() << endl;
	la2.show();
}

在这里插入图片描述
构造函数

  1. 以类名作为函数名
  2. 无返回值类型

作用
3. 初始化对象的数据成员
4. 类对象被创建时,编译器为对象分配内存空间并自动调用构造函数以完成成员的初始化

构造函数的种类
5. 无参构造
6. 一般构造
7. 拷贝构造
在这里插入图片描述
注意:

  1. 如果创建的类中未书写任何构造函数,系统会自动生成默认的无参数构造函数(函数为空, 什么都不做)
  2. 如果书写了构造函数,系统就不会再自动生成默认构造;如果希望有一个这样的无参构造函数,需要自己显示地书写出来。

Land2.h

#pragma once

#include <string>
#include <memory>

using namespace std;

class Land2
{
	//省略了private
	string name;
	long score; //解决积分为负数错误的方法,将成员变量score进行隐藏并封装
	int cards[20];
public:
	
	Land2();//默认构造
	~Land2();

	void show();

	//使用方法/函数实现对成员变量的封装Get/Set方法
	void SetScore(long lscore)
	{
		if (lscore < 0)
			score = 0;//如果传入的积分是非法情况, 那么积分默认为0;
		else
			score = lscore;//积分为正数时, 才进行赋值操作, 这里就通过条件判断,封装了score的赋值过程
	}
	string GetName();

	void SetName(string na);
};


Land2.cpp

#include "Land2.h"

#include <iostream>

Land2::Land2()
{
	//一般使用构造函数进行成员变量的初始化
	name = "默认地主";
	score = 0;
	//将用户的手牌数组初始化为0
	memset(cards, 0, sizeof(cards));
	cout << "Land2的无参构造函数(默认构造)被调用!" << endl;
	cout << "初始化的结果如下:" << endl;
	cout << "名称:" << name << endl;
	cout << "积分:" << score << endl;
	cout << "手牌数组:";
	for (int i = 0; i < sizeof(cards) / sizeof(cards[0]); i++)
	{
		cout << cards[i] << ", ";
	}
	cout << endl;
}


Land2::~Land2()
{
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件
#include "Land2.h"

using namespace std;

int main()
{
	//Land2 land2;
	Land2 land2; 
}

显示

Land2的无参构造函数(默认构造)被调用!
初始化的结果如下:
名称:默认地主
积分:0
手牌数组:0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

带类构造 ——函数重载
在这里插入图片描述
Land3.h

#pragma once
#include <iostream>
#include <string>

using namespace std;

class Land3
{
public:
	//构造函数的重载规则与普通函数的重载相同
	Land3();
	Land3(int); //如果构造函数中,只有一个带参 可以简化:Land3 L3 = 50;
	Land3(string, string);//带参构造
	~Land3();

	void ShowInfo();

	string GetName() { return m_name; }
	void SetName(string val) { m_name = val; }
	string Getdesc() { return m_desc; }
	void Setdesc(string val) { m_desc = val; }
	int Getage() { return m_age; }
	void Setage(int val)
	{
		if (val < 0)
			m_age = 18;
		else
			m_age = val;
	}

protected:

private:
	string m_name;
	string m_desc;
	int m_age;

};

Land3.cpp

#include "Land3.h"



Land3::Land3()
{
	cout << "默认构造" << endl;

}

Land3::Land3(int age)
{
	Setage(age);
	cout << "调用带参构造:Land3::Land3(int age)" << endl;
}

Land3::Land3(string name, string desc) : m_name(name), m_desc(desc) //初始化参数列表简写
{
	//m_name = name;//等价写法  SetName(name);
	//m_desc = desc;
	cout << "调用带参构造:Land3::Land3(string name, string desc)" << endl;
}

void Land3::ShowInfo()
{
	cout << m_desc << m_name << endl;
}

Land3::~Land3()
{
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件
#include "Land2.h"
#include "Land3.h"

using namespace std;

int main()
{
	Land3 L1; //在栈内存中直接分配内存,(宝贵)
	Land3 L2("马", "架体");
	Land3 l3(35);
	Land3 L4 = 46;
	L2.ShowInfo();

	Land3* l5 = new Land3("jieke", "huichuangali");//指针型,在堆内存里面新分配一个空间
	l5->ShowInfo();
}

显示结果

默认构造
调用带参构造:Land3::Land3(string name, string desc)
调用带参构造:Land3::Land3(int age)
调用带参构造:Land3::Land3(int age)
架体马
调用带参构造:Land3::Land3(string name, string desc)
huichuangalijieke

栈内存和堆内存
**栈内存:**由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。若分配失败,则提示栈溢出错误。注意,const局部变量也储存在栈区内,栈区向地址减小的方向增长。

**堆内存:**程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则则导致内存泄露。

析构函数

  1. 对象过期时自动调用的特殊成员函数
  2. 析构函数一般用来完成清理工作
  3. 析构函数的名称是在类名前加上==~==
  4. 析构函数没有参数, 只能有一个
    在这里插入图片描述
    注意:
    1、 析构函数用来释放对象使用的资源,并销毁对象的非static(静态)数据成员
    2、无论何时一个对象被销毁, 都会自动调用其析构函数(隐式结构)
    land3.cpp
#include "Land3.h"



Land3::Land3()
{
	cout << "默认构造" << endl;

}

Land3::Land3(int age)
{
	Setage(age);
	cout << "调用带参构造:Land3::Land3(int age)" << endl;
}

Land3::Land3(string name, string desc) : m_name(name), m_desc(desc) //初始化参数列表简写
{
	//m_name = name;//等价写法  SetName(name);
	//m_desc = desc;
	cout << "调用带参构造:Land3::Land3(string name, string desc)" << endl;
}

void Land3::ShowInfo()
{
	cout << m_desc << m_name << endl;
}

Land3::~Land3()
{
	cout << m_name << "被释放" << endl; //栈内存自动被释放
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件
#include "Land2.h"
#include "Land3.h"

using namespace std;

int main()
{
	Land3 L1; //在栈内存中直接分配内存,(宝贵)
	Land3 L2("马", "架体");
	Land3 l3(35);
	Land3 L4 = 46;
	L2.ShowInfo();

	Land3* l5 = new Land3("jieke", "huichuangali");//指针型,在堆内存里面新分配一个空间
	l5->ShowInfo();

	//当对象使用完毕时,记得delete 释放内存(堆内存)
	delete l5;
}

实现结果

默认构造
调用带参构造:Land3::Land3(string name, string desc)
调用带参构造:Land3::Land3(int age)
调用带参构造:Land3::Land3(int age)
架体马
调用带参构造:Land3::Land3(string name, string desc)
huichuangalijieke
jieke被释放
被释放
被释放
马被释放
被释放

使用类创建对象

第一种实例化对象
栈内存中创建:类似声明变量
在这里插入图片描述
第二种实例化方式
在碓内存中创建:需要new关键字
在这里插入图片描述
练习
在这里插入图片描述
数组的替代品——容器

向量容器Vector

  • 动态数组,可以在运行阶段设置长度
  • 具有数组的快速索引方式
  • 可以插入和删除元素

定义和初始化

vector<double> vec1;
vector<string> vec2(5);
vector<int> vec3(20, 998);

在这里插入图片描述
Land3.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include <ctime>

using namespace std;

class Land
{
private:
	string m_NickName;
	string m_Sex;
	int m_Gold;
	long m_Exp;
	vector<int> packCards; //默认的一副牌,从1到54
	vector<int> surplusCards; //摸牌后剩余的牌
	vector<int> currCards; //当前玩家的手牌数组
	bool isContains(int); //剩余牌中是否包含cardNum这个牌面

	void deleteCard(vector<int>&, int); //删除集合中的数字

	string getColor(int);//获得牌的花色
	string getValue(int);//获得牌面

public:
	Land();
	Land(string);
	Land(string, string, int, long);
	~Land();

	string GetNickName() { return m_NickName; }
	void SetNickName(string NickName) { m_NickName = NickName; }
	string GetSex() { return m_Sex; }
	void SetSex(string Sex) { m_Sex = Sex; }
	int GetGold() { return m_Gold; }
	void SetGold(int val) { m_Gold = val; }
	long GetExp() { return m_Exp; }
	void SetExp(long val) { m_Exp = val; }

	void TouchCard(int);//摸牌

	void ShowInfo();

	void InitCards();//初始化packCards、surplusCards、currCards

	void ShowCards(const vector<int>&); //显示集合中的牌面 传引用 内存效率会更高,const防止传引用误更改引用的值
protected:

};

Land3.cpp

#include "Land.h"

Land::Land()
{
	SetNickName("默认地主");
	SetSex("保密");
	SetExp(0);
	SetGold(100);
	cout << "Land()" << endl;
	InitCards();
}

Land::Land(string nickname) : m_NickName(nickname)
{
	SetSex("保密");
	SetExp(0);
	SetGold(100);
	cout << "Land(string nickname)" << endl;
	InitCards();

}

Land::Land(string nickname, string sex, int gold, long exp) : m_NickName(nickname), m_Sex(sex), m_Gold(gold), m_Exp(exp)
{
	cout << "Land(string nickname, string sex, int gold, long exp)" << endl;
	InitCards();
}

void Land::ShowInfo()
{
	cout << "昵称:" << GetNickName() << endl;
	cout << "性别:" << GetSex() << endl;
	cout << "金币:" << GetGold() << endl;
	cout << "经验:" << GetExp() << endl;
}

void Land::InitCards()
{
	//生成默认的一幅扑克牌
	for (int i = 0; i < 54; i++)
	{
		packCards.push_back(i + 1);
		surplusCards.push_back(packCards.at(i));
	}
	currCards.clear();

	ShowCards(surplusCards);
}

void Land::ShowCards(const vector<int>& cards)
{
	C语言的习惯
	//for (int i = 0; i < cards.size(); i++)
	//{
	//	cout << cards[i] << ", ";
	//}
	//cout << endl;

	c++, 使用迭代器
	//for (vector<int>::const_iterator iter = cards.begin(); iter != cards.end(); iter++)
	//{
	//	cout << *iter << ", ";
	//}
	//cout << endl;

	使用c++11 的类型推断 auto
	//for (auto iter = cards.begin(); iter != cards.end(); iter++)
	//{
	//	cout << *iter << ", ";
	//}
	//cout << endl;

	//使用c++11 for区间遍历
	for (auto card : cards)
	{
		cout << card << ":" << getColor(card) << "-" << getValue(card) << ", ";
	}
	cout << endl;

	使用算法的方式, 将容器的内容复制到cout 绑定的迭代器中
	要用到两个头文件 #include<iterator> #include<algorithm>
	//copy(cards.cbegin(), cards.cend(), ostream_iterator<int>(cout, ", "));
	//cout << endl;
}

void Land::TouchCard(int cardCount)
{
	srand(time(NULL)); //时间种子
	//随机生成一张剩余牌集合中有的牌, 添加到currCards集合中, 从surrplusCards中删除这张牌
	for (int i = 0; i < cardCount; i++)
	{
		int randIndex = rand() % 54; //0-53之间的随机数字
		//判断:随机生成的这张牌是否在剩余牌集合中
		if (isContains(packCards[randIndex]))
		{
			currCards.push_back(packCards[randIndex]); //将摸的牌放入当前手牌数组
			//在剩余排钟删除摸的牌
			deleteCard(surplusCards, packCards[randIndex]);
		}
		else
		{
			i--;//重新摸牌
		}
	}
	cout << "地主摸牌:当前手牌如下:" << endl;
	ShowCards(currCards);
	cout << "地主摸牌后:剩余牌面如下:" << endl;
	ShowCards(surplusCards);
}

bool Land::isContains(int cardNum)
{
	普通青年的做法:
	//for (int i = 0; i < surplusCards.size(); i++)
	//{
	//	if (surplusCards[i] == cardNum)
	//	{
	//		return true;
	//	}
	//}
	//return false;

	//使用算法来查找
	vector<int>::iterator iter = find(surplusCards.begin(),surplusCards.end(), cardNum);
	/*if (iter == surplusCards.end())
	{
		return false;
	}
	return true;*/
	return iter != surplusCards.end();
}

void Land::deleteCard(vector<int>& cardVec, int card)
{
	普通青年的做法
	//for (auto iter = cardVec.begin(); iter != cardVec.end();)
	//{
	//	if (*iter == card)
	//	{//如果找到就删除
	//		iter = cardVec.erase(iter);//这里返回值指向已删除的下一个元素
	//	}
	//	else
	//	{
	//		++iter;//继续判断下一个元素是否相同
	//	}
	//}

	//使用算法删除
	auto iter = find(cardVec.begin(), cardVec.end(), card);
	if (iter != cardVec.end())
	{
		cardVec.erase(iter);
	}
}

string Land::getColor(int card) // 注意这里 card 不是下标
{
	if (card == 53) return "小王";
	if (card == 54) return "大王";
	string colors[] = {
		"黑桃", "红心", "方块", "梅花"
	};
	return colors[(card - 1) / 13];
}

string Land::getValue(int card)
{
	if (card == 53) return "Black Joker";
	if (card == 54) return "Red Joker";
	string value[] = {
		"A", "2", "3", "4", "5", "6", "7", "8",
		"9", "10", "J", "Q", "K"
	};
	return value[(card - 1) % 13];
}

Land::~Land()
{
	cout << GetNickName() << "被释放" << endl;
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件
#include "Land2.h"
#include "Land3.h"
#include "Land.h"

using namespace std;

int main()
{
	Land* ptr_L1 = new Land(); 
	ptr_L1->ShowInfo();
	Land* ptr_L2 = new Land("专业斗地主");
	ptr_L2->ShowInfo();
	Land* ptr_L3 = new Land("傻瓜");
	ptr_L3->ShowInfo();

	ptr_L2->TouchCard(20);

	delete ptr_L1;
	delete ptr_L2;
	delete ptr_L3;

	return 0;
}

结果

Land()
1:黑桃-A, 2:黑桃-2, 3:黑桃-3, 4:黑桃-4, 5:黑桃-5, 6:黑桃-6, 7:黑桃-7, 8:黑桃-8, 9:黑桃-9, 10:黑桃-10, 11:黑桃-J, 12:黑桃-Q, 13:黑桃-K, 14:红心-A, 15:红心-2, 16:红心-3, 17:红心-4, 18:红心-5, 19:红心-6, 20:红心-7, 21:红心-8, 22:红心-9, 23:红 心-10, 24:红心-J, 25:红心-Q, 26:红心-K, 27:方块-A, 28:方块-2, 29:方块-3, 30:方块-4, 31:方块-5, 32:方块-6, 33:方块-7, 34:方块-8, 35:方块-9, 36:方块-10, 37:方块-J, 38:方块-Q, 39:方块-K, 40:梅花-A, 41:梅花-2, 42:梅花-3, 43:梅花-4, 44:梅花-5, 45:梅花-6, 46:梅花-7, 47:梅花-8, 48:梅花-9, 49:梅花-10, 50:梅花-J, 51:梅花-Q, 52:梅花-K, 53:小王-Black Joker, 54:大王-Red Joker,
昵称:默认地主
性别:保密
金币:100
经验:0
Land(string nickname)
1:黑桃-A, 2:黑桃-2, 3:黑桃-3, 4:黑桃-4, 5:黑桃-5, 6:黑桃-6, 7:黑桃-7, 8:黑桃-8, 9:黑桃-9, 10:黑桃-10, 11:黑桃-J, 12:黑桃-Q, 13:黑桃-K, 14:红心-A, 15:红心-2, 16:红心-3, 17:红心-4, 18:红心-5, 19:红心-6, 20:红心-7, 21:红心-8, 22:红心-9, 23:红 心-10, 24:红心-J, 25:红心-Q, 26:红心-K, 27:方块-A, 28:方块-2, 29:方块-3, 30:方块-4, 31:方块-5, 32:方块-6, 33:方块-7, 34:方块-8, 35:方块-9, 36:方块-10, 37:方块-J, 38:方块-Q, 39:方块-K, 40:梅花-A, 41:梅花-2, 42:梅花-3, 43:梅花-4, 44:梅花-5, 45:梅花-6, 46:梅花-7, 47:梅花-8, 48:梅花-9, 49:梅花-10, 50:梅花-J, 51:梅花-Q, 52:梅花-K, 53:小王-Black Joker, 54:大王-Red Joker,
昵称:专业斗地主
性别:保密
金币:100
经验:0
Land(string nickname)
1:黑桃-A, 2:黑桃-2, 3:黑桃-3, 4:黑桃-4, 5:黑桃-5, 6:黑桃-6, 7:黑桃-7, 8:黑桃-8, 9:黑桃-9, 10:黑桃-10, 11:黑桃-J, 12:黑桃-Q, 13:黑桃-K, 14:红心-A, 15:红心-2, 16:红心-3, 17:红心-4, 18:红心-5, 19:红心-6, 20:红心-7, 21:红心-8, 22:红心-9, 23:红 心-10, 24:红心-J, 25:红心-Q, 26:红心-K, 27:方块-A, 28:方块-2, 29:方块-3, 30:方块-4, 31:方块-5, 32:方块-6, 33:方块-7, 34:方块-8, 35:方块-9, 36:方块-10, 37:方块-J, 38:方块-Q, 39:方块-K, 40:梅花-A, 41:梅花-2, 42:梅花-3, 43:梅花-4, 44:梅花-5, 45:梅花-6, 46:梅花-7, 47:梅花-8, 48:梅花-9, 49:梅花-10, 50:梅花-J, 51:梅花-Q, 52:梅花-K, 53:小王-Black Joker, 54:大王-Red Joker,
昵称:傻瓜
性别:保密
金币:100
经验:0
地主摸牌:当前手牌如下:
16:红心-3, 54:大王-Red Joker, 31:方块-5, 6:黑桃-6, 10:黑桃-10, 33:方块-7, 38:方块-Q, 5:黑桃-5, 27:方块-A, 24:红心-J, 12:黑桃-Q, 44:梅花-5, 49:梅花-10, 8:黑桃-8, 28:方块-2, 42:梅花-3, 36:方块-10, 41:梅花-2, 22:红心-9, 14:红心-A,
地主摸牌后:剩余牌面如下:
1:黑桃-A, 2:黑桃-2, 3:黑桃-3, 4:黑桃-4, 7:黑桃-7, 9:黑桃-9, 11:黑桃-J, 13:黑桃-K, 15:红心-2, 17:红心-4, 18:红心-5, 19:红心-6, 20:红心-7, 21:红心-8, 23:红心-10, 25:红心-Q, 26:红心-K, 29:方块-3, 30:方块-4, 32:方块-6, 34:方块-8, 35:方块-9, 37:方块-J, 39:方块-K, 40:梅花-A, 43:梅花-4, 45:梅花-6, 46:梅花-7, 47:梅花-8, 48:梅花-9, 50:梅花-J, 51:梅花-Q, 52:梅花-K, 53:小王-Black Joker,
默认地主被释放
专业斗地主被释放
傻瓜被释放

this关键字

this指针

  • 每个成员函数(包括构造和析构)都有一个this指针
  • this指针指向调用对象,既可以通过this关键字访问当前对象的成员
    在这里插入图片描述
  • 可以用来返回当前对象的引用
    在这里插入图片描述
    Land3.h
#pragma once
#include <iostream>
#include <string>

using namespace std;

class Land3
{
public:
	//构造函数的重载规则与普通函数的重载相同
	Land3();
	Land3(int); //如果构造函数中,只有一个带参 可以简化:Land3 L3 = 50;
	Land3(string, string);//带参构造
	~Land3();

	void ShowInfo();

	string GetName() { return m_name; }
	void SetName(string val) { m_name = val; }
	string Getdesc() { return m_desc; }
	void Setdesc(string val) { m_desc = val; }
	int Getage() { return m_age; }
	void Setage(int val) 
	{
		if (val < 0)
			m_age = 18;
		else
			m_age = val;
	}

	void InitScores(); //初始化学生成绩数组,默认分配一个元素空间
	void AddScore(float); //向scores数组中添加一个分数

	//书写函数, 要求返回学霸对象
	Land3& GetSuperScholar(Land3&); //const;
	float GetTotal();

protected:

private:
	string m_name;
	string m_desc;
	int m_age;
	int scoreCount;//学生的成绩个数
	float* scores;//学生的分数数组
};

Land3.cpp

#include "Land3.h"



Land3::Land3()
{
	cout << "默认构造" << endl;

}

Land3::Land3(int age)
{
	Setage(age);
	cout << "调用带参构造:Land3::Land3(int age)" << endl;
	InitScores();
}

Land3::Land3(string name, string desc) : m_name(name), m_desc(desc) //初始化参数列表简写
{
	//m_name = name;//等价写法  SetName(name);
	//m_desc = desc;
	cout << "调用带参构造:Land3::Land3(string name, string desc)" << endl;
	InitScores();
}

void Land3::ShowInfo()
{
	cout << m_desc << m_name << endl;
	for (int i = 0; i < scoreCount - 1; i++)
	{
		cout << this->scores[i] << "\t";
	}
	cout << endl;
}

//void Myshow(const Land3* thiz) //c的写法 this在c++中是函数的隐含的第一个参数;
//{
//	thiz->AddScore;
//}

void Land3::InitScores()
{
	this->scores = new float[1];
	this->scoreCount = 1;
}

void Land3::AddScore(float score)
{
	this->scores[this->scoreCount - 1] = score;
	//1、创建一个新数组、分配scorecount + 1个空间
	//2、复制一个元素组的内容到新数组中
	//3、scoreCount++
	//4、scores指向新数组

	float* newScores = new float[scoreCount + 1];
	float* oldScores = scores;
	memcpy(newScores, scores, sizeof(float) * scoreCount);
	scoreCount++;
	scores = newScores;
	delete oldScores;
}

float Land3::GetTotal()
{
	float sum = 0;
	for (int i = 0; i < scoreCount - 1; i++)
	{
		sum += scores[i];
	}
	return sum;
}

/*返回学霸对象
*@param otherStu 要对比的另外一个学生对象
*@return 返回总分比较大的那个学生对象
*/
 Land3& Land3::GetSuperScholar(Land3& otherStu)
{
	//分别计算两个学生的总分
	if (this->GetTotal() > otherStu.GetTotal())
	{
		return *this;//返回当前对象的引用
	}
	else
	{
		return otherStu;
	}
}

Land3::~Land3()
{
	cout << m_name << "被释放" << endl; //栈内存自动被释放
	//delete this->scores;
}

main.cpp

#include <iostream>
#include "Land1.h"    //如果要实用类,必须要包含类的头文件
#include "Land2.h"
#include "Land3.h"
#include "Land.h"

using namespace std;

int main()
{
	/*Land* ptr_L1 = new Land(); 
	ptr_L1->ShowInfo();
	Land* ptr_L2 = new Land("专业斗地主");
	ptr_L2->ShowInfo();
	Land* ptr_L3 = new Land("傻瓜");
	ptr_L3->ShowInfo();

	ptr_L2->TouchCard(20);

	delete ptr_L1;
	delete ptr_L2;
	delete ptr_L3;*/

	Land3* ptrL1 = new Land3("diyihfdis", "asdjfha");

	ptrL1->AddScore(78.9f);
	ptrL1->AddScore(100.2f);
	ptrL1->AddScore(68.5f);
	ptrL1->AddScore(45.7f);
	ptrL1->AddScore(99.9f);
	ptrL1->ShowInfo();

	Land3 L2( "akjsdkj", "sjdhfh" );
	L2.AddScore(56.8f);
	L2.AddScore(98.4f);
	L2.AddScore(86.4f);
	L2.AddScore(45.6f);
	L2.AddScore(76.8f);

	Land3& scholar1 = L2.GetSuperScholar(*ptrL1); //返回ptrL1的引用
	Land3& scholar2 = ptrL1->GetSuperScholar(L2);
	cout << "学霸是:" << scholar1.GetName() << endl;
	cout << "学霸是:" << scholar2.GetName() << endl;

	delete ptrL1;

	return 0;
}

结果

调用带参构造:Land3::Land3(string name, string desc)
asdjfhadiyihfdis
78.9    100.2   68.5    45.7    99.9
调用带参构造:Land3::Land3(string name, string desc)
学霸是:diyihfdis
学霸是:diyihfdis
diyihfdis被释放
akjsdkj被释放
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值