C++:类和对象

1.概念:根据下图我们可以直观的了解类和对象

类:对现实生活中事物的描述

对象:对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。

注:ADT为抽象数据类型 

2.创建:

[修饰符] class类名

{

private:

    成员变量;

public:

    成员方法

}

C++三大特征:封装、继承、多态

 封装:举个简单通俗例子,你向朋友借钱,你应该向他发送信号说我要借钱,朋友说可以,这时应该等待朋友给你取钱,而你不能直接从朋友衣服中取钱,封装就是这样的,简单说就是该给你看的给你看,属于公有的(public),不该给你看的不能看,属于私有的(private)。继承和多态暂不讨论。

类中限定访问符:1.public:任意位置可以访问

                             2.protected:本类、子类中可以访问

                             3.private:本类类中访问

 例:学生类的成员变量为:姓名、学号、年龄           成员方法为:吃饭、睡觉、打豆豆

class Student
{
public:
	void eat()// Student*const this隐藏指针
	{
		//this = &s1;
		std::cout << this->mname << " is eating" << std::endl;
		std::cout << this->mage << std::endl;
	}
	void sleep()
	{
		std::cout << mname << " is sleeping" << std::endl;
	}
	void play()
	{
		std::cout << mname << " is playing  doudou" << std::endl;
	}
	
private:
	char* mname;
	char* mid;
	int mage;
};

 

3.struct当成类处理

在C++中struct当成类处理,与C语言中不同的是:在类中默认访问符是私有的(private),struct中默认为公有的(public)

4.this(thiscall):类中普通的成员方法中默认的参数,this

我们使用时代码为: 

void eat()
{
    std::cout<<mname<<"is eating"<<std::endl;
}

实际隐藏的完整代码为:

void eat(   this)
{
    std::cout<<this->mname<<"is eating"<<std::endl;
}

5.成员方法在类中/外实现:

类中:默认内联函数inline

类外:普通方法(有开栈、清栈过程)

6.类中六个默认函数:分为公有的、inline

例:实体为商品,成员变量为:名字、价格、数量    成员方法:买、卖


  1.构造函数 :初始化对象的内存空间,函数名和类名相同,无返回值
     特点:可以重载、不能手动调用、顺序构造

系统默认:CGoods(){}
自己提供:CGoods(char* name, float price, int amount)
	{
		std::cout << this << " :CGoods::CGoods(char*,float,int)" << std::endl;
		mname = new char[strlen(name) + 1]();
		strcpy(mname, name);
		mprice = price;
		mamount = amount;
	}

调用点:CGoods good("car",10.1,10);//初始化对象内存


  2.析构函数:释放对象所占的其他资源
     特点:不可重载、可以手动调用,即退化成普通函数的调用、先构造的后析构

~CGoods()
{
	std::cout << this << " :CGoods::~CGoods()" << std::endl;
	delete[] mname;
}


  3.拷贝构造函数:用已存在的对象来生成一个相同类型的新对象
     特点:形参用&接收、防止递归构造形参对象导致栈溢出

CGoods(const CGoods& rhs)
{
	std::cout << this << " :CGoods::CGoods(const CGoods&)" << std::endl;
	mname = new char[strlen(rhs.mname) + 1]();
	strcpy(mname, rhs.mname);
	mprice = rhs.mprice;
	mamount = rhs.mamount;
}
调用点: CGood good1("car1",10,1,10);
        CGood good2=goog1;//CGood good2(good1);

注:默认拷贝构造函数是一个浅拷贝,重复释放的堆内存,程序崩溃 

 将红色部分释放,good2则变为野指针

  4.赋值运算符的重载函数:把一个已存在的对象赋值给相同类型的已存在对象

实现过程:
  1.判断是否自赋值
  2.释放旧资源
  3.申请新资源
  4.赋值 

CGoods& operator=(const CGoods& rhs)
{
	std::cout << this << " :CGoods::operator=(const CGoods&)" << std::endl;
	if (this != &rhs)//判断是否自赋值
	{
		delete[] mname;//释放旧资源
		mname = new char[strlen(rhs.mname) + 1]();//申请新资源
		strcpy(mname, rhs.mname);//赋值
		mprice = rhs.mprice;
		mamount = rhs.mamount;
	}
	return *this;
}
调用点:
CGoods good1("good1", 10.5, 20);
CGoods good2;
good2 = good1;

注:系统提供的的默认赋值运算符重载函数是 浅拷贝 

const作用:
 1.防止修改实参
 2.接收隐式生成的临时对象 

以下两种默认函数暂不讨论:
  5.取地址操作符的重载函数
  6.const修饰的取地址操作符的重载函数

 

7、临时量
  1.内置类型的临时量:常量
  2.自定义类型的临时量:变量
  3.隐式生存的临时量:常量
  4.临时对象的生存周期:表达式结束

临时量的优化
  1.以生成临时对象的方式生成新对象

CGood good4(10);

 此行代码,是将int类型作为形参传递生成一个CGood类型,明显不适合,所以将10生成一个带有一个参数的CGoodt类型临时对象,再调用拷贝构造函数,用已存在的对象来生成一个相同类型的对象,而临时对象的生成周期为表达式结束,所以在遇到分号“;”时,再调用析构函数释放临时对象。

2.引用能提升临时对象的生存周期:把临时对象提升和引用变量相同的生存周期 

CGoods& rgood12 = CGoods("good11", 10.1, 20);

 此行代码,是显式生成一个带有三个参数的CGood类型的临时对象,再调用拷贝构造函数,用已存在的对象来生成一个相同类型的对象,而临时对象的生成周期为表达式结束,但使用引用符号“&”,能提升临时对象的生存周期,把临时对象提升和引用变量相同的生存周期,所以本应该在遇到分号时,调用析构函数,但延长生存周期后,在程序结束时才会调用析构函数。

 练习:分析每一行代码所存储的位置,以及调用的函数、生存周期

CGoods ggood1("good1", 10.1, 20);//.data
int main()
{
	CGoods good3;
	CGoods good4(good3);

	good4 = good3;

	static CGoods good5("good5", 10.1, 20);//.data

	CGoods good6 = 10;
	CGoods good7(10);
	CGoods good8 = CGoods("good8", 10.1, 20);

	good6 = 20;
	good7 = CGoods(20);
	good8 = (CGoods)("good8",10.1, 20);

	CGoods* pgood9 = new CGoods("good9", 10.1, 20);//heap
	CGoods* pgood10 = new CGoods[2];

	CGoods* pgood11 = &CGoods("good11", 10.1, 20);
	CGoods& rgood12 = CGoods("good11", 10.1, 20);
	const CGoods& rgood13 = 20;

	delete pgood9;
	delete[] pgood10;

	return 0;
}
CGoods ggood2("good2", 10.1, 20);//.data

 9、构造函数的初始化列表
      初始化顺序和初始化列表的顺序无关
      和成员变量/对象的声明顺序有关

Test(int a,int b):ma(a),mb(b)
{}


 10、常对象和常方法:
      常对象不能调用普通方法
      常对象只能调用常方法
      普通对象也可以调用常方法
      普通方法可以调用常方法
      常方法不能调用普通方法

void Show()const
{}
//将this指针修饰为const Test *const类型

      常成员变量:一定要初始化  (构造函数的初始化列表中)

Stu (const Stu&rhs):birth(rhs.birth);

11、static
  1.修饰成员变量:不属于对象独享 、对象共享、一定要在类外初始化、不依赖对象访问

static  int ma;
int Text::ma=10;//注意使用时需要加作用域

2.修饰成员方法:(_cdecl  没this指针)不能访问普通成员变量、可以访问静态的成员变量和全局变量、
                             静态的成员方法不能调用普通的成员方法
                             普通的成员方法可以调用静态的成员方法

12、类编译过程(顺序)

 1.类名
 2.类成员名称
 3.成员方法的形参,默认值
 4.方法体 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值