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

【C++】类与对象(上篇:基础知识讲解)

程序员文章站 2024-03-15 18:46:24
...

1.面向过程和面向对象初步认识

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
例如:如何将大象装进冰箱?
第一步:打开冰箱
第二步:把大象塞进冰箱
第三步:关上冰箱…

C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
例如:把车开走。抽象两个对象:人和车。具体描述人与车的信息及各自的功能,通过人对象和车对象相互之间的交互,把车开走。

2.类的引入

C语言中,结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。

struct Student 
{    
	void SetStudentInfo(const char* name, const char* gender, int age)    
	{        
	strcpy(_name, name);        
	strcpy(_gender, gender);        
	_age = age;    
	}        
	void PrintStudentInfo()    
	{        
	cout<<_name<<" "<<_gender<<" "<<_age<<endl;    
	}        
	char _name[20];    
	char _gender[3];    
	int _age; 
};
int main() 
{    
	Student s;    
	s.SetStudentInfo("Peter", "男", 18); 
	s.PrintStudentInfo();
	return 0; 
}
 

在C++中更喜欢用class来代替。

3.类的定义

class className
{
	//由成员变量和成员函数组成
};//注意分号

class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。
类的两种定义方式:
1.声明和定义全部放在类体中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

class Person
{
public:
	void showInfo()
	{
		cout<<_name<<" "<<_gender<<" "<<_age<<endl;
	}
public:
	char _name[20];
	char _gender[3];
	int _age;
};

2.声明放在.h文件中,类的定义放在.cpp文件中
Person.h

class Person
{
public:
	void showInfo();
public:
	char _name[20];
	char _gender[3];
	int _age;
};

Person.cpp

#include "Person.h"
void Person::showInfo()
{
	cout<<_name<<" "<<_gender<<" "<<_age<<endl;
}

一般情况下采用第二种方式

4.类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。

class Person
{
public:
	void showInfo();
public:
	char _name[20];
	char _gender[3];
	int _age;
};

void Person::showInfo()//需写上Person::
{
	cout<<_name<<" "<<_gender<<" "<<_age<<endl;
}

5.类的实例化

用类类型创建对象的过程,称为类的实例化。类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量 。
打个比方:类就好比设计房子的图纸,类实例化处的对象就好比根据图纸建造出的房子。
【C++】类与对象(上篇:基础知识讲解)

6.类的访问限定符及封装

6.1 访问限定符
访问限定符包括:public(公有)private(私有)protected(保护)
说明
1.public修饰的成员在类外可以直接被访问
2.protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
4. class的默认访问权限为private,struct为public(因为struct要兼容C)
6.2 封装
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
举例:C++如何实现封装特性?
采用class来定义类,将数据和方法进行有机结合,class默认访问权限是private,所有成员都不能在类外被直接使用,通过访问限定符,提供公有的接口来让对象之间交互。

7.类对象大小的计算

一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比 较特殊,编译器给了空类一个字节来唯一标识这个类。
举例:类对象s1的大小为28字节

class Student
{
public:
	void SetStudentInfo(char name[], char gender[], int age, char school[])
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}

	void PrintStudentInfo()
	{
		cout << _name << "-" << _gender << "-" << _age << endl;
	}

public:
	char _name[20];
	char _gender[3];
	int  _age;
};
int main()
{
	Student s1, s2, s3;

	// 要检测Student类对象有多大:至少要知道对象中都包含了那些成员
	s1.SetStudentInfo("熊大", "公", 5, "熊熊乐园");
	s2.SetStudentInfo("熊二", "母", 4, "熊熊乐园");
	s3.SetStudentInfo("强哥", "男", 28, "森林大学");

	s1.PrintStudentInfo();
	s2.PrintStudentInfo();
	s3.PrintStudentInfo();
	cout << sizeof(s1) << endl;//28 注意内存对齐 20+3+1+4=28
	return 0;
}

8.类成员函数的this指针

class Student
{
public:
	void SetStudentInfo(char name[], char gender[], int age, char school[])
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}

	void PrintStudentInfo()
	{
		cout << _name << "-" << _gender << "-" << _age << endl;
	}

public:
	char _name[20];
	char _gender[3];
	int  _age;
};
int main()
{
	Student s1, s2, s3;

	// 要检测Student类对象有多大:至少要知道对象中都包含了那些成员
	s1.SetStudentInfo("熊大", "公", 5, "熊熊乐园");
	s2.SetStudentInfo("熊二", "母", 4, "熊熊乐园");
	s3.SetStudentInfo("强哥", "男", 28, "森林大学");

	s1.PrintStudentInfo();
	s2.PrintStudentInfo();
	s3.PrintStudentInfo();
	return 0;
}

如上代码,Student类中有SetStudentInfo与PrintStudentInfo两个成员函数,函数体中没有关于不同对象的区分,那当s1调用SetStudentInfo函数时,该函数是如何知道应该设置s1对象,而不是设置s2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

实际代码如下:

class Student
{
public:
	void SetStudentInfo(Student* const thischar name[], char gender[], int age);
	{
		strcpy(this->_name, name);
		strcpy(this->_gender, gender);
		this->_age = age;
	}
	void PrintStudentInfo(Student* const this)
	{
		cout << this->_name << "-" << this->_gender << "-" << this->age << endl;
	}
public:
	char _name[20];
	char _gender[3];
	int _age;
};

this指针的特性
1.只能在“成员函数”的内部使用
2.this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
3.this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。