欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++类与对象一:OOP思想、类和对象、this指针

程序员文章站 2024-03-16 10:27:58
...

一、OOP思想

什么是OOP思想?
       面向对象的程序设计语言必须有描述对象及其相互之间关系的语言成分。这些程序设计语言可以归纳为以下几类:系统中一切事物皆为对象;对象是属性及其操作的封装体;对象可按其性质划分为类,对象成为类的实例;实例关系和继承关系是对象之间的静态关系;消息传递是对象之间动态联系的唯一形式,也是计算的唯一形式;方法是消息的序列。

面向对象基本概念:
C++类与对象一:OOP思想、类和对象、this指针
(1)对象
对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。
(2)对象的状态和行为
对象具有状态,一个对象用数据值来描述它的状态。
对象还有操作,用于改变对象的状态,操作就是对象的行为。
对象实现了数据和操作的结合,使数据和操作封装于对象的统一体中
(3)类
具有相同或相似性质的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象。
类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。
类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。
(4)类的结构
在客观世界中有若干类,这些类之间有一定的结构关系。通常有两种主要的结构关系,即一般–具体结构关系,整体–部分结构关系。
①一般——具体结构称为分类结构,也可以说是“或”关系,或者是“is a”关系。
②整体——部分结构称为组装结构,它们之间的关系是一种“与”关系,或者是“has a”关系。
(5)消息和方法
对象之间进行通信的结构叫做消息。在对象的操作中,当一个消息发送给某个对象时,消息包含接收对象去执行某种操作的信息。发送一条消息至少要包括说明接受消息的对象名、发送给该对象的消息名(即对象名、方法名)。一般还要对参数加以说明,参数可以是认识该消息的对象所知道的变量名,或者是所有对象都知道的全局变量名。
类中操作的实现过程叫做方法,一个方法有方法名、参数、方法体。‘
简单举个例子来瞧瞧吧:
C++类与对象一:OOP思想、类和对象、this指针
OOP思想四大特征:抽象、封装,继承、多态
1.抽象:忽略一个主题中与当前目标无关的东西,专注的注意与当前目标有关的方面,将其抽象。
抽象包括两个方面,一个数据抽象,而是过程抽象。
数据抽象 -->表示世界中一类事物的特征,就是对象的属性.比如鸟有翅膀,羽毛等(类的属性)
过程抽象 -->表示世界中一类事物的行为,就是对象的行为.比如鸟会飞,会叫(类的方法)

2.封装:只隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:将变化隔离、便于使用、提高复用性、提高安全性
原则:将不需要对外提供的内容隐藏起来;把属性隐藏,提供公共方法对其访问

3.继承:提高代码复用性;继承是多态的前提。
注:
①子类中所有的构造函数都会默认访问父类中的空参数的构造函数,默认第一行有super();若无空参数构造函数,子类中需指定;另外,子类构造函数中可自己用this指定自身的其他构造函数。

4.多态:是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。
好处:提高了程序的扩展性
弊端:当父类引用指向子类对象时,虽提高了扩展性,但只能访问父类中具备的方法,不可访问子类中的方法;即访问的局限性。
前提:实现或继承关系;覆写父类方法。

二、类和对象:模拟一个商品类

访问限定符: public公有的 private私有的 protected保护的

注意:成员方法可以在类内定义,也可以在类外定义。类体内实现的方法,自动处理为inline内联函数。类体外实现的成员方法需要在方法名前加类的作用域,它是普通的函数。

商品类:

//Author:Mr.Rain
#include <iostream>
using namespace std;

const int NAME_LEN = 20;

//商品类
class CGoods  //=>商品的抽象类型,不占空间,类型定义的对象才占空间。
{
public://给外部提供公有的成员方法来访问私有的属性
	void init(char *name, double price, int amount);//商品数据初始化
	void show();//打印商品信息
	//给成员变量提供一个getXXX()或setXXX的方法,调用接口给对象的成员变量赋值
	//类体内实现的方法,自动处理为inline内联函数。
	void setName(char *name) { strcpy(_name,name); }
	void setPrice(double price) { _price = price; }
	void setAmount(int amount) { _amount = amount; }

	const char* getName(){ return _name; }
	double getPrice() { return _price; }
	int getAmount() { return _amount; }
private://属性一般为私有成员变量
	char _name[NAME_LEN];
	double _price;
	int _amount;
};

void CGoods::init(char *name, double price, int amount)//商品数据初始化
{
	strcpy(_name, name);
	_price = price;
	_amount = amount;
}
void CGoods::show()//打印商品信息
{
	cout << "name:" << _name << endl;
	cout << "price:" << _price << endl;
	cout << "amount:" << _amount << endl;
}

int main()
{
	CGoods good1;//类实例化了一个对象

	good1.init("面包", 10.0, 200);
	good1.show();

	cout << "修改后的:-----------------------------" << endl;
	good1.setPrice(20.5);
	good1.setAmount(100);
	good1.show();

	cout << "---------------------------------------" << endl;
	CGoods good2;
	good2.init("空调", 10000.0, 50);
	good2.show();

	return 0;
}

对象的内存大小只和成员变量有关,与结构体计算方式一样。
也可以通过VS命令提示符查看:

命令格式:cl /d1reportSingleClassLayout[ClassName]

三、this指针

this指针:类的成员方法一经编译,所有的方法参数,都会加一个this指针,接收调用该方法的对象的地址。使用时可以上也可以不加,编译器默认会补上。

       我们了解了类可以定义无数的对象,每一个对象都有自己的成员变量,但是它们共享一套成员方法。但是成员方法是如何知道处理哪个对象的信息?
例如:我们上面的show()方法怎么知道处理哪个对象的信息?init(name,price,amount)怎么知道把信息初始化给哪一个对象的呢?这就需要我们的this指针了。
如图,这是我们刚才的例子:
简单来看,谁调用我,我就处理谁的数据;底层来说,其实是将调用这个方法对象的地址传入进去。

//init(&good1, "面包" , 10.0, 200)
good1.init("面包", 10.0, 200);
//show(&good1);
good1.show();

其实质与C没有什么区别,汇编语言上差不多。既然传入了实参,也要添加形参。实参是地址类型,形参就需要指针来接受。编译器编译时,给所有的成员方法都会加上*this指针。

void init(CGood *this, char *name, double price, int amount);
void show(CGood *this);
void setName(CGood *this,char *name) { strcpy(_name,name); }
void setPrice(CGood *this,double price) { _price = price; }
void setAmount(CGood *this,int amount) { _amount = amount; }
const char* getName(CGood *this){ return _name; }
double getPrice(CGood *this) { return _price; }
int getAmount(CGood *this) { return _amount; }

       这就是一套方法能知道处理哪个对象的原因:因为当用对象调用这些方法的时候,他就把对象的地址当作实参传给这些函数了,这些函数在编译过程中会产生this指针来接收所传入函数的地址。

参考博客:什么是面向对象思想