目录
C++的四大基本特征:(面向对象的思想oop)
1、抽象:提取现实世界中某事物的关键特性,为该事物构建模型的过程。
2、封装:使类具有独立性和隔离性;保证类的高内聚。
三个访问限定符:public:在任意位置(类中、类外)
protected:在本类类中和子类类中访问
private:本类类中。
3、继承:对现有类的一种复用机制
4、多态:多态是在继承的基础上实现的。
三要素:继承、重写和父类引用指向子类对象。
父类引用指向不同的子类对象时,调用相同的方法,呈现出不同的行为就是类多态特性。
栈上的特点:系统开辟、系统释放
堆上的特点:手动开辟、手动释放
对象的生成:
①开辟内存;
②系统调用构造函数对于开辟内存做初始化。
对象的销毁:
①:资源的释放(释放对象所占其他资源),调动析构函数;
②:释放内存。
类中的六个默认函数
1、构造函数
作用:初始化对象的内存空间
特点:①默认构造;(有this指针)
②可以重载;
③不能手动调用(构造函数是生成对象,所以不能手动调用)
class CGoods
{
public:
//构造函数
CGoods(char* name, float price, int amount)
{
mname = new char[strlen(name) + 1];
//初始化
strcpy(mname, name);
mprice = price;
mamount = amount;
}
//析构函数
~CGoods()
{
delete[]mname;
mname = NULL;//防止野指针出现
}
private:
char*mname;
float mprice;
int mamount;
};
2、析构函数
作用:释放对象所占资源
特点:①不能重载;(有this指针)
②可以手动调用(不建议使用);(析构函数退化成普通成员方法)->系统还会调用一次析构函数
3、拷贝构造函数
作用:拿一个已存在的对象来生成相同类型的新对象。
特点:①默认的拷贝构造函数(浅拷贝)
如果类成员变量有指针,考虑实现深拷贝。
②形参一定加引用(不加会导致递归生成形参对象,形参对象无法生成)
浅拷贝:只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化。
深拷贝:将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变。
4、赋值运算符的重载函数
作用:拿一个已存在的对象来赋值给另一个相同类型的已存在的对象。
默认的赋值运算符重载函数的设计流程:
①自赋值的判断;
②释放旧的资源;
③开辟新的资源;
④赋值。
形参const:
①防止修改实参;
②接收隐式生成的临时量;
临时对象
什么是临时对象?
swap方法中,常常定义一个temp对象,这个temp对象不是临时对象,而是局部对象。
为什么会产生临时对象?
a、客户期望的数据与你提供的数据不一致,需要隐式类型转换,中间需要适配一下,建立一个临时对象。
b、方法返回值,他是没有名字的,起到一个传递作用,方法内部的局部对象-->方法返回值-->主调方法中的接受对象。
c、异常处理,分为两个过程:抛出异常,捕获异常。抛出异常相当于return 方法内的局部对象,外部要有一个匿名的临时对象接收。catch语句类似于调用方法,将临时对象传给catch语句。
什么情况会产生临时对象?
a、以值的方式给函数传参;
函数传参有两种方式。1,按值传递;2,按引用传递。按值传递时,首先将需要传给函数的参数,调用拷贝构造函数创建一个副本,所有在函数里的操作都是针对这个副本的,也正是因为这个原因,在函数体里对该副本进行任何操作,都不会影响原参数。
b、类型转换;
做类型转换时,转换后的对象通常是一个临时对象。
c、函数需要返回一个对象时。
当函数需要返回一个对象,他会在栈中创建一个临时对象,存储函数的返回值。
临时对象的优化:
如果临时对象的生成是为了生成新的对象,就以生成临时对象的方式生成新的对象。
优化->为了生成新对象->以生成临时对象的方式来生成新的对象。
临时对象的生存周期
在表达式之后。
引用能提升临时对象的生存周期。(把临时对象的生存周期提升成和引用对象相同的生存周期)
临时量:
①内置类型生成的临时量是常量(临时量,寄存器带出来)。
②自定义类型生成的临时量是变量 ,在内存中。
③隐式生成生成的临时量是常量 ,显式生成生成的临时量是变量 。
生存周期:
类类型的返回值:都是由临时对象带出来的。
class CGoods
{
public:
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()
{
std::cout << this << "CGoods::CGoods()" << std::endl;
mname = new char[1];
}
CGoods(int amount)
{
mname = new char[1];
std::cout << this << "CGoods::CGoods(int)" << std::endl;
mamount = amount;
}
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;
}
void operator=(const CGoods& rhs)//CGoods* const this//赋值运算符重载函数
{
std::cout << this << "CGoods::operator=(const CGoods&) ->" << &rhs << std::endl;
if (this == &rhs)
{
return;
}
delete[] mname;
mname = new char[strlen(rhs.mname) + 1];
strcpy(mname, rhs.mname);
mprice = rhs.mprice;
mamount = rhs.mamount;
}
//void Init(char* name, float price, int amount)
//{
// mname = new char[strlen(name) + 1];
// strcpy(mname, name);
// mprice = price;
// mamount = amount;
//}
void Buy()
{
--mamount;
}
void Sell()
{
++mamount;
}
~CGoods()//析构函数
{
delete[] mname;
std::cout << this << "CGoods::~CGoods()" << std::endl;
mname = NULL;//防止野指针的出现
}
/*
~CGoods(){}
*/
/*void Destroyed()
{
delete[] mname;
mname = NULL;
}*/
private:
char* mname;
float mprice;
int mamount;
};
int main()
{
CGoods good1("car1", 100000, 10);
CGoods good2 = good1;//CGoods good2(good1);
CGoods good3;
//good3 = good1;
good3 = 10;//CGoods int==>CGoods
good3 = CGoods(10);//临时对象
//good3 = CGoods("good3")//显示生成临时对象
//good3 = "good3"//隐式生成的临时对象
//int a = 10.1;
return 0;
}
5、取地址操作符重载函数
6、const修饰的取地址操作符的重载函数