C++面向对象总结(一)对象产生、this指针、引出拷贝构造和赋值运算符重载函数

1.面向对象的三大特征:
封装:访问限定符,public、protected、private
继承: 继承与派生,一般为public继承
多态:虚函数+基类指针指向派生类对象,调用派生类中同名同参的函数

2.class和struct的区别
1.在c++中struct和class没什么区别,既然是在c++中,就尽量使用class;

2.c和c++跨语言中有一定的区别,区别如下:
2.1 c中的struct访问限定默认是public的,c++中的struct或者class默认是private的;
2.2 空结构的体在c中大小不确定,因为编译器不同,结果也不同,必然windows上vs,编译不通过,linux有兴趣的可以试试;
在c++中,空结构体或者空class默认大小为1byte,因为在c++为定义变量,实际上是实例化一个对象,我们不可能在一个大小为0的内存上调用构造函数去实例化对象,所以默认分配1字节;

//c++中class和struct没有区别
//定义空类
class A{};
struct B{};

int main()
{
	A a;
	B b;
	cout << sizeof(a) << endl;
	cout << sizeof(A) << endl;
	cout << sizeof(b) << endl;
	cout << sizeof(B) << endl;

	return 0;
}
执行结果:
1
1
1
1

3.实现一个物品类: 注意看函数内的注释

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

class CGoods
{
public:
    //类内定义的函数,默认被编译器处理为inline函数
    //使用的是   _thiscall   函数调用约定
	CGoods(char *const name, int count, float price)
	{
		if (name == NULL)
		{
		_name = new char;
		 *_name = '\0';
		}

		_name = new char[strlen(name) + 1];
		strcpy(_name,name);

		_count = count;
		_price = price;
	}
	void show();
	void setname(char *name){ strcpy(_name, name); }
	void getname(char *name){ strcpy(name, _name); }
	//char *getname(){ return _name ;}   
	//该函数会将_name的地址返回回去,如果类外拿到地址,可以通过地址解引用来修改内存中的值,不满足面向对象的封装
	float getprice(){  return _price; }
	~CGoods()
	{
		delete _name;
		_name = NULL;
	}
private:
	char *_name;
	int _count;
	float _price;
};

//类外实现,函数名前加上类的作用域,告诉编译器产生的这个函数符号是类的作用域下的
void CGoods::show() 
{ 
	cout << "name: " << _name << "price: " << _price << "count:" << _count << endl; 
}
//类外实现的成员方法,不会被处理为内联函数,除非我们手动加上  inline
// inline void CGoods::show() 
int main()
{
	CGoods c1("苹果",10,8.9);
	c1.show();
	return 0
}
执行结果:
name: 苹果 price: 8.9 count:10

类不占内存,只是对现实实物的抽象说明,对象才占内存;
成员方法不占内存,是指令;成员变量才占内存。

4.this指针是什么,有什么用?
从上面的函数调用的结果可以看到,show函数打印出了c1的内容,
那么编译器怎么指定show就是要打印c1的内容呢。
c1.show()看似没有给函数传参数,实际上默认有一个参数:CGoods *const this
this:指针保存的是调用该函数的对象的地址
这样编译器就知道要show谁的信息,谁调用该方法,this保存的就是谁的内存;
这个是隐式生成的,不需要我们手动的添加,编译器自动添加,我们可以直接使用。

5.对象怎么产生的,什么时候产生?
对象由构造函数生成,当构造函数调用完成,对象才真正的产生;
我们在栈上定义一个对象,仅仅给对象分配了栈上的内存,内存的内容可能是0xcccccccc,所以需要构造函数进行初始化。
其中this指针始终指向的就是这块内存,所以构造析构都有this指针

6.构造函数和析构函数:
1.如果我们没有提供自定义的构造和析构函数,系统会给我们产生默认的构造和析构函数,默认产生的也是内联函数,只不过是空函数;
2.构造函数可以重载,但是析构函数不可以;
(举个不恰当的例子,人生来就不同(构造),死的时候都一样(析构))
3.如果我们提供的相应的构造或者析构函数,系统将不再给产生默认的析构或者构造函数;
4.对象的构造和析构是系统给我们调用的,构造函数是在定义对象的时候调用的,析构函数是在出右括号 ‘{’ 的时候调用的
5.构造函数不能自己调,就像人不能选择自己的出生一样,析构可以自己调,就像人可以选择自己的结束。

7.分清对象的内存和对象外部资源:
对象的内存:对象本身占用的内存,由系统分配;
对象外部资源:除对象本身内存以外的内存,如对象成员变量绑定的一块堆内存,一个文件描述符等
构造函数:初始化对象的成员变量,开辟对象以外的资源;
析构函数:释放对象的外部资源。

8.构造和析构的顺序:
先构造的后析构,后构造的先析构,就像入栈和出栈的顺序一样;

9.分清调用默认构造和函数声明:

CGood c1("香蕉",10,99);
CGood c2();    //函数声明
CGood c3;     //不给传参数,认为调用默认的构造函数;

10.分清初始化和赋值的概念:
初始化:右值还不存在,还在定义;
赋值:右值已经存在了,然后给顶其他的值。

11.构造函数的重载之 拷贝构造函数

实参到形参是初始化的过程,一步能完成为什么要两步呢

CGoods c2 ( c3 );    CGoods c2 = c3;
//拷贝构造函数,用同类型已经存在的对象 构造 同类型正在定义的对象
CGoods (CGoods const  &src)
1.拷贝构造函数的构造不能按值传递,会造成递归的拷贝构造,因为实参到形参是一个初始化的过程; 所以我们一般按引用接收实参,指针也可以,但是既然有引用了干嘛还有用指针呢?
2.const保证不被修改;

12.赋值运算符的重载函数

c2 = c1;
//赋值运算符的重载,用已经存在的对象  赋值 给已经存在的相同类型的对象

(拷贝构造函数和赋值运算符重载函数实现在下一篇文章中实现)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值