C++笔记_03面向对象1,2

#if 1
#include<iostream>
using namespace std;




/*
1.用函数指针调用和 用函数名调用函数的区别
函数的调用有标准的函数栈帧的开辟与回退
同伙函数指针调用函数的时候::  1.在编译阶段不可能被处理成内联函数
2.看起来累赘
???


*/


/*
面向过程


面向对象OOP


面向对象语言的三大特征 封装  继承 多态


封装和隐藏
访问限定符
public 公有的  哪里都可以访问
proteced 保护的
private 私有的  除了类自己可以访问,其他谁的都不能访问


1.
struct class 有什么区别???


struct 成员默认是共有的
一个空结构体占用零个字节,
windows vc/vs  下建立C文件试试  看看是否可以建立空结构体
linux  gcc  




class  成员默认是私有的
空的类  占用 一个字节  






与C语言的调用约定不同
C语言函数使用的标准的C调用
C++用的是thiscall
??? thiscall???
*/


struct Node   
{
int data;
Node *pnext;//在C语言中不可以如此写,编译通不过;在C++中 此处已经处理成一个类类型
//struct Node *Pnext;//在C语言中这样写
};




// this指针   -》  指向调用该成员方法的对象,不能用关键字定义变量名


/*
C语言中  结构体 -》 产生的变量  -》分配内存


C++  类-》 对象
1.分配内存
2.调用相应的构造函数 -> 构造完成之后 -> 对象存在了
 
 若没有提供任何的构造函数和析构函数,系统会为你产生默认的构造和默认的析构函数
 若你提供了任意一个构造函数,那么系统就不会再产生默认的构造函数
 //???  提供了析构函数之后,系统还会默认提供吗


 系统产生的函数 有两个特点 public和inline的
 //自己定义的呢


*/




/*
系统(编译器)调用构造函数,析构函数的点


构造函数:  在定义对象的时候调用的,内存的开辟和构造函数的调用是一起的
构造函数不能手动调用,是编译器根据情况自己调用的
析构函数:  return的时候析构  出} 之前,出}之后是进行函数栈帧的回退
析构函数可以随意次数调用,在对象是存在的情况下。 与编译器调用的析构不冲突,
但是,最好不要调用,资源释放之后容易产生错误


***构造函数不是给对象分配内存,只是对对象的内存初始化
***析构函数不是释放对象的内存,是在对象内存没有之前 对象占用的其他资源释放掉


先构造的后析构,后构造的先析构,和出入栈的方法是一样的








作业:  用OOP 写顺序栈和循环队列
*/




























class CGoods
{
public:
//通过访问公有的成员方法,来简介的访问私有的成员变量
//成员方法 _thiscall


//构造函数   可以带参数   可以有多个  可以重载
CGoods()//Register()  //  也存在隐式的this指针
{
cout<<this<<endl;
cout<<"CGoods()"<<endl;
_pname = new char[1];   //一般得不到数据的情况,给资源都要分配内存
_pname = '\0';
_amount = 0;
_price = 0.0;
}
//explicit:禁止隐式对象生成的关键字


CGoods(char *name,int amount,float price)
{
cout<<this<<endl;
cout<<"CGoods(char *,int ,float )"<<endl;
_pname = new char[strlen(name)+1];
strcpy(_pname,name);
_amount=amount;
_price=price;
}


//拷贝构造函数 生成新对象
//CGoods good3=good2; //两个对象共享拷贝构造函数,
//对象自己的成员 可以任意访问自己的其他任何访问限定的成员方法和成员变量


CGoods(const CGoods &src) //预习实现    //拷贝构造
{
cout<<&src<<"->"<<this<<endl;
cout<<"CGoods(const CGoods &)"<<endl;
_pname=new char[strlen(src._pname)+1];
strcpy(_pname,src._pname);
_amount=src._amount;
_price = src._price;
}
//系统有默认的拷贝构造函数     不是空函数,对象的内存互相初始化
/*拷贝构造的时候,系统会调用默认的拷贝构造函数,
//会将good2中的值放到good3中,但是good3的指针指向的也是good2的内存
//发生浅拷贝   若good2或者good3提前调用析构函数,那么剩下的那个会成为野指针
//所以当对象调用了默认的拷贝构造函数会发生浅拷贝的时候应该自己写拷贝构造函数,
//浅拷贝,,不完全拷贝,,, 
当对象占用了除自己内存以外的其他系统资源拷贝构造会发生浅拷贝
*/


//赋值运算符的重载函数
//good1 = good2
//void operator = (const CGoods src)  //这样也可以,但是效率不高。

//进行深拷贝,避免浅拷贝
/*
成员方法const的意义
1. 保护实参不被修改
2.
*/
/* 
内置类型 产生的临时量都是常量(都放在了寄存器当中),不能被修改
自定义类型 产生的临时量都是变量,可以被修改


隐式产生的临时量都是常对象 所以常对象必须要用常引用  const &
*/
void operator = (const CGoods &src)//对象赋值的时候会调用//与拷贝构造函数共用
{
//此处const是为了保护实参不被修改
cout<<&src<<"->"<<this<<endl;
cout<<"operator=(const CGoods&)"<<endl;
//防止自赋值(自己给自己赋值)
if(this == &src)
return;


//释放当前对象占用的其他的系统资源
delete []_pname;
_pname = NULL;


_pname = new char[strlen(src._pname)+1];//给当前对象分配新的资源
strcpy(_pname,src._pname);//拷贝资源
_amount = src._amount;
_price = src._price;
}




//析构函数  不能带参数  有且只能有一个
~CGoods()//Release()
{
cout<<this<<endl;
cout<<"~CGood()"<<endl;
if(_pname != NULL)
delete []_pname;
_pname = NULL;
}


void Register(char *name,int amount,float price);//对 对象进行初始化的动作  赋初始值/分配资源
//调用是void Register(CGoods *const this,char *name,int amount,float price);
//c++ 会在每个成员函数第一个参数隐式生成this对象指针
//使用成员变量的时候也一样  会有隐式的this指针


void Release()// 清理对象占用的其他系统资源
{
if(_pname != NULL)
delete []_pname;
}








void Show();


//在类体里面实现的成员函数,自动被编译器处理成inline函数
void SetName(char *name){strcpy(_pname,name);}//在定义体内实现函数的定义
void SetAmount(int amount){_amount=amount;}
void SetPrice(float price){_price=price;}


void GetnName(char *name){strcpy(name,_pname);}
//char* GetnName(){return _name;}   //不安全,指针解引用可以更改_name的值


int GetAmount(){return _amount;}
float GetPrice(){return _price;}


private://访问限定 
char *_pname;//抽象说明  不占用空间下同
int   _amount;
float _price;
};


//void Register(char *name,int amount,float price)// 这样写就是标准的C调用
void CGoods::Register(char *name,int amount,float price)  //C++中 外部调用要声明作用域
{
_pname = new char[strlen(name)+1];
strcpy(_pname,name);
_amount=amount;
_price=price;
}


void CGoods:: Show()
{
cout<<"name:"<<_pname<<endl;
cout<<"amount:"<<_amount<<endl;
cout<<"price:"<<_price<<endl;
}






int main()
{
/*
编译器有


默认的构造函数   空
默认的析构函数 空


默认的拷贝构造函数  非空,是对象的内存互相初始化
***若按照值进行传参,会发生拷贝构造的递归调用


默认的operator=赋值运算符的重载函数  对象的内存相互赋值

为了避免浅拷贝,
最好提供自定义的拷贝构造  赋值运算符的重载函数




类和对象的基础    的考点
各种对象的生命周期
//todo  查
*1  临时对象的生存周期 -> 临时对象所在的语句
用临时对象【构造】同类型的新对象的时候,此时,临时对象不生成,(编译器优化)
用构造临时对象的方式直接构造目标对象
此时 
CGodds good4 = CGoods("shangpin2",30,12.5);//显示生成临时对象
等效于
CGoods good4("shangpin2",30,12.5);
用临时对象【赋值】的时候,会构造临时对象,临时对象生成,将临时对象赋值
完成后,临时对象析构 
遇到; ? ,时结束


-题外-  ,逗号表达式(1,2,3,4); 最后只会留下4
//good1 = (CGoods)12.5; //good1 = CGoods(12.5);  这两个都是显示生成临时对象
[能看见类名是显示生成临时对象,看不见类名就是隐式]


*2 类类型 <-> 其他类型


其他类型 -> 类类型:: 
::看该类有没有构造函数,以 其他类型 作为参数,隐式生成一个临时对象
eg: good1 = 89.5;
类类型 -> 其他类型::
::


*3
CGoods *p = &CGoods("shangpin2",30,12.5);//出了该语句,临时变量就会析构,指针就成了野指针

CGoods &q = CGoods("shangpin2",30,12.5);//临时对象周期 提升 引用变量的生存周期


       **千万不能用一个指针指向一个临时量


*4 类对象的生存周期
void test(CGoods *p)
{
cout<<"call test"<<endl;
p->show();
}
传入一个临时对象,在这个函数退出的时候析构




*/


/*

*/


CGoods good1; 


CGoods good2("shanpin",10,4.5);


CGoods good3 = good2; //是初始化,不是赋值
/*拷贝构造的时候,系统会调用默认的拷贝构造函数,
//会将good2中的值放到good3中,但是good3的指针指向的也是good2的内存
//发生浅拷贝   若good2或者good3提前调用析构函数,那么剩下的那个会成为野指针
//所以当对象调用了默认的拷贝构造函数会发生浅拷贝的时候应该自己写拷贝构造函数,
//浅拷贝,,不完全拷贝,,, 
当对象占用了除自己内存以外的其他系统资源拷贝构造会发生浅拷贝
*/
//


//good2.Show();




//赋值  没有产生新对象  默认的赋值会发生浅拷贝 和内存泄露
// good1.operator=(good3);   对象任何的运算都相当于成员方法的调用,所以
// 对象等号的调用也相当于一个函数的调用
// void operator = (cosnt CGgoods &src);
//good1.operator = (good3);
// CGoods::operator = (&good1,good3);
good1 = good3;




return 0;
}


#endif


/*
int main()
{
//CGoods::CGoods (&good1)
CGoods good1;  //默认调用默认构造函数


//CGoods::CGoods (&good2,"shanpin",10,4.5)
CGoods good2("shanpin",10,4.5); // 默认调用带有对应参数的构造函数
//Cgoods good3();   //不能手动调用默认构造函数,此处会认为是函数的声明,加()一定要有参数

//初始化    赋值
//CGoods good3(good2);
//good3.CGoods(good2);


//CGoods(cosnt CGoods &src);  //引用 &src
//-> 拷贝构造函数 用同类型已经存在的对象构造同类型的新对象
//  拷贝构造函数不能按照对象的值进行传递 -> 会引起递归构造
CGoods good3 = good2;   //  ->  CGood good3(good2);


good2.Show();


//good1.Register("商品1",200,8.5);
//good1.Show();
//.show  的左边必须有类/结构/联合
//good1.Release();






//
//CGoods good1;
//CGoods good2;


调用的时候其实是传入了四个参数  CGoods::Register(&good1,"商品1",200,8.5)
最后一个传入的是函数的调用地址 
//good1.Register("商品1",200,8.5);
//good1.Show();


//good2.Register("商品2",100,10.5);
//good2.Show();
//






return 0;
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值