第3章 类和对象(1)

类和对象(1)

一、类和对象的基本概念

1.结构体与类

结构体的扩充

(1)C++语言对结构体类型进行了扩充,它不仅可以含有不同类型的数据,而且还可以含有函数。
(2)在C++中,通常把结构体中的数据称为数据成员,把函数称为成员函数。

用扩充的结构体类型求复数的绝对值
#include<iostream>
#include<cmath>
using namespace std;
struct Complex{//声明了一个名为Complex的结构体类型
	double real;//数据成员,复数的实部
	double imag;//数据成员,复数的虚部
	void init(double r,double i){//成员函数,给real和image赋初值
		real=r;
		imag=i;
		}
	double abscomplex(){//成员函数,求复数的初始值
		double t;
		t=real*real+imag*imag;
		return sqrt(t);
	}
}int main()
{
	Complex A;//定义结构体的Complex的变量A
	A.init(1.1,2.2);//调用成员函数init,给real和image赋初值
	cout<<"复数的绝对值是:"<<A.abscomplex()<<endl;//调用成员函数abscomplex
	return 0;
}
程序运行结果如下:
复数的绝对值是:2.45967

类的声明

类与结构体的扩充形式非常相似,例如,上面的结构体类型Complex可以改写成如下:

……
using namespace std;
class Complex{//用关键字class取代结构体的struct,声明了一个名为Complex的类
double real;
……

类类声明的一般形式如下:

class 类名{
	[private:]
	私有成员数据和成员函数
	public:
	公有数据成员和成员函数
}

2.成员函数的定义

类的成员函数是函数的一种,它也有函数名返回值类型和参数表,用法与普通函数基本是一样的,只是它属于一个类的成员。

成员函数的第一种定义:在类声明中只给出成员函数的原型,而将成员函数的定义放在类的外部。

返回值类型 类名::成员函数名(参数表)
{
    函数体
}
表示坐标点的类Point可声明如下:
class Point{
	public:
		void setpoint(int,int);//设置坐标点的成员函数setpoint的函数原型
		int getx();//取x坐标点的成员函数getx的函数原型
		int gety();//取y坐标点的成员函数gety的函数原型
	private:
		int x,y;
};
void Point::setpoint(int a,int b)//在类外定义成员函数setpoint
{
	x=a;
	y=b;
}
int Point::getx()//在类外定义成员函数getx
{
	return x;
} 
int Point::gety()//在类外定义成员函数gety
{
	return y;
}

成员函数的第二种定义方式是:将成员函数直接定义在类的内部。
成员函数的第三种定义方式是:为了书写清晰,在类声明中只给出成员函数的原型,而将成员函数的定义放在类的外部。但是在类内函数原型声明前或在类外定义成员函数前冠以关键字inline,以此显式地说明这是一个内联函数。这种定义内联函数的方法称为显式定义。

3.对象的定义及使用

类与对象的关系

C++把类的变量叫做类的对象,对象也称为类的实例。

对象的定义

(1)在声明类的同时,直接定义对象,即在声明类的右花括号“}”后,直接写出属于该类的对象名表。
(2)声明了类之后,在使用时再定义对象。定义对象的格式与定义基本数据类型变量的格式一致,其一本形式如下:
类名 对象名1,对象名2,……;

说明:
声明了一个类便声明了一种类型,它并不接收和存储具体的值,只作为生成具体对象的一种“样板”,只有定义了对象后,系统才为对象分配存储空间,以存放对象中的成员。

对象中成员的访问

不论是数据成员,还是成员函数,只要是公有的,在类的外部可以通过类的对象进行访问。访问对象中的成员有以下三种方法。
(1)通过对象名和对象选择符访问对象中的成员。
对象名.数据成员名

对象名.成员函数名[(实参表)]
其中“ . ”叫做对象选择符,简称点运算符。
(2)通过指向对象的指针访问对象中的成员
在定义对象时,若我们定义的是指向此对象的指针,则访问此对象的成员时,不能用“ . ”操作符,而应使用“->”操作符。
(3)通过对象的引用访问对象中的成员
如果为一个对象定义了一个引用,也就是为这个对象起了一个别名。因此完全可以通过引用来访问对象中的成员,其方法与通过对象名来访问对象中的成员时相同的。

4.类的作用域和类成员的访问属性

二、构造函数和析构函数

构造函数是属于某一个类的,它可以由用户提供,也可以由系统自动生成。析构函数,当撤销类的对象时,析构函数就回收存储空间,并做一些善后工作。

1.对象的初始化和构造函数

构造函数是一种特殊的成员函数,它主要用于为对象分配空间,进行初始化。
(1)构造函数的名字必须以类名相同,而不能由用户任意命名。
(2)它可以有任意类型的参数,但不能具有返回值类型。它不需要用户来调用,而是在建立对象时自动执行的。

为类Complex建立一个构造函数
class Complex {
	private:
	double real;//表示复数的实部
	double imag;//表示复数的虚部
	public:
	Complex (double r,double i)//定义构造函数,其名与类名相同
	{
		real=r;imag=i;//在构造函数中,对私有数据real和image赋值
	}
	double abscomplex()
	{
		double t;
		t=real*real+imag*imag;
		return sgrt(t);
		}
	};

在建立对象的同时,采用构造函数给数据成员赋初值,通常有以下两种形式。
形式1:
类名 对象名[(实参表)];
这里的“类名”与构造函数名相同,“实参表”是为构造函数提供的实际参数。
形式2:
类名 * 指针变量名=new 类名[(实参表)];
这是一种使用new运算符动态建立对象的方式。

说明:
(1)构造函数的名字必须以类名相同,否则编译程序将它当作一般的成员函数来处理。
(2)构造函数没有返回值,在定义构造函数时,是不能说明它的类型的,甚至说明为void类型也不行。
(3)与普通的成员函数一样,构造函数的函数体可写在类体内,也可写在类体外。
(4)构造函数的作用主要是用来对对象进行初始化,用户根据初始化的要求设计函数体和函数参数。
(5)构造函数一般声明为公有成员,但它也不需要也不能像其他成员函数那样被显式地调用,它是在定义对象的同时被自动地调用的,而且只执行一次。
(6)在实际应用中,通常需要给每个类定义构造函数。如果没有给类定义构造函数,则编译系统自动地生成一个默认构造函数。
(7)构造函数可以不带参数。

2.用成员初始化列表对数据成员初始化

不在函数体内用赋值语句对数据成员初始化,而是在函数首部实现的。
带有成员初始化列表的构造函数的一般形式如下:
类名 :: 构造函数名([参数表])[: (成员初始化列表)]
{
// 构造函数体
}
成员初始化列表的一般形式为:
数据成员名1(初始值1),数据成员名2(初始值2),……

3.构造函数的重载

(1)如果在类中用户没有定义构造函数,系统会自动提供一个函数体为空的默认构造函数。
(2)尽管一个类中可以包含多个构造函数,但对于一个对象而言,建立对象时只执行其中的一个构造函数。

4.带默认参数的构造函数

(1)如果构造函数在类的声明外定义,那么默认参数应该在类内声明构造函数原型时指定,而不能在类外构造函数定义时指定。
(2)如果构造函数的全部参数都指定了默认值,则在定义对象时可以指定1个或几个实参,也可以不给出实参,这时的构造函数也属于默认构造函数。
(3)在一个类中定义了全部是默认参数的构造函数之后,不能再定义重载构造函数。

5.析构函数

析构函数有以下一些特点:
(1)析构函数名与类名相同,但它前面必须加一个波浪号(~)。
(2)析构函数不返回任何值。在定义析构函数时,是不能说明它的类型的,甚至说明为void类型也不行。
(3)析构函数没有参数,因此不能被重载。一个类可以有多个构造函数,但是只能有一个析构函数。
(4)撤销对象时,编译系统会自动地调用析构函数。

说明:
(1)每个类必须有一个析构函数。若没有显式地为一个类定义析构函数,则编译系统会自动生成一个默认析构函数。
(2)除了在主程序结束(或调用exit函数)时,对象被撤销,系统会自动调用析构函数外,在以下情况,析构函数也会被调用:
A:如果一个对象被定义在一个函数体内,则当这个函数被调用结束时,该对象将释放,析构函数被调用。
B:若一个对象是使用new运算符动态创建时,在使用delete运算符释放它时,delete会自动调用析构函数。

三、对象数组与对象指针

1.对象数组

所谓对象数组是指一个数组元素都是对象的数组,也就是说,若一个类有若干个对象,我们把这一系列的对象用一个数组来存放。对象数组的元素是对象,不仅具有数据成员,而且还有成员函数。
定义一个一维数组的格式如下:
类名 数组名 [下标表达式];
在使用对象数组时只能访问单个数组元素,其一般形式是:
数组名[下标].成员名

2.对象指针

每一个对象在初始化后都会在内存中占有一定的空间。因此,既可以通过对象名访问一个对象,也可以通过对象地址来访问一个对象。对象指针就是用于存放对象地址的变量。声明对象指针的一般语法形式为:
类名 * 对象指针名;

(1). 用指针访问单个对象成员
一般情况下,用点运算符“.”来访问对象成员,当用指向对象的指针来访问对象成员时,就要用“->”操作符。
(2). 用对象指针访问对象数组
对象指针不仅能引用单个对象,也能访问对象数组。

3.this指针

(1)C++为成员函数提供一个名字为this的指针,这个指针称为自引用指针。每当创建一个对象时,系统就把this指针初始化为指向该对象,即this指针的值是当前调用成员函数的对象的起始地址。
(2)this指针是隐式使用的,它是作为参数被传递给成员函数的。

四、string类

在C++的标准库中,声明了一种字符串类型,即字符串类string,类string提供了对字符串进行处理所需的操作。
使用string类必须在程序的开始包括头文件string,即要有如下语句:
#include< string >
string类的字符串对象必须先定义才可以使用。其定义格式如下:
string 对象1,对象2,……;

五、向函数传递对象

1.使用对象作为函数参数

在向函数传递对象时,是通过“传值调用”传递给函数的,即单向传递,只由实参传给形参,而不能由形参传回来给实参。因此函数中对对象的任何修改均不影响调用该函数的对象(实参)本身。

2.使用对象指针作为函数参数

对象的指针可以作为函数的参数,使用对象指针作为函数参数可以实现“传址调用”,即在函数调用时使实参对象和形参对象指针变量指向同一内存地址,在函数调用过程中,对形参对象指针所指对象值得改变也同样影响着实参对象的值。
当函数的形参是对象指针时,调用函数的对应实参应该是某个对象的地址值。

3.使用对象引用作为函数参数

使用对象引用作为函数参数不但具有对象指针用作函数参数的优点,而且用对象引用作函数参数将更简单、更直接。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值