C++程序与设计(第四版,郑莉)----(第四章)

本文介绍了面向对象编程中的基本概念,包括类的抽象、封装、继承和多态,以及类和对象的定义、成员函数、构造与析构函数、类的组合和UML图形标识。还对比了结构体与联合体的特点和使用场景。
摘要由CSDN通过智能技术生成

第四章类与对象

41面向对象程序设计的基本特点

4.1.1抽象

        :对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程。

分数据抽象与功能(行为)抽象

4.1.2封装

        :将抽象得到的数据与行为相结合形成一个整体(类)

//类----封装
class Clock
{
//行为抽象
public:
	void SetTime(int newH, int newM, int newS);
	void ShowTime();
	//数据抽象
private:
	int hour, minute, second;


};

4.1.3继承

把特殊与一般的概念间的关系描述清楚,使特殊概念之间既能共享一般的属性与行为,又具有特殊的属性与行为。

继承

        :提供类的继承,允许保持原有类特性的基础上进行更具体的详细说明(第七章)

4.1.4多态

        :指一段程序能处理多种类型对象的能力,可通过强制多态,重载多态,类型参数化多态,包含多态,4中方法实现(第八章,第九章细说)

4.2类和对象

4.2.1类的定义

类使面向对象程序设计方法的核心,类可以实现对数据的封装和隐蔽,是对问题的抽象描述,描述一类对象的共同属性与行为

//类----封装
class Clock
{
//函数成员
public://外部接口
	void SetTime(int newH, int newM, int newS);
	void ShowTime();
protected://保护型成员
	
private://私有数据成员
	int hour, minute, second;

4.2.2类成员的访问控制

类成员:函数成员与数据成员

访问控制属性分:共有类型,保护类型,私有类型

共有类型是外部接口(public)

私有成员只能被本类的成员函数访问

保护与私有类型相似但是在继承过程中产生新类的影响不同

修饰访问类型的关键字可以多次出现

class Clock
{
//函数成员
public://外部接口
	void SetTime(int newH, int newM, int newS);
	

public :
		void ShowTime();
private://私有数据成员
	int hour, minute, second;


};

4.2.3对象

        :该类的实体

对象所占据的内存空间只用于存放数据成员,函数成员在内存只占据一份空间

class Clock
{
//函数成员
public://外部接口
	void SetTime(int newH, int newM, int newS);
	

public :
		void ShowTime();
private://私有数据成员
	int hour, minute, second;


};
int main()
{
	Clock myclock;
	myclock.SetTime;

4.2.4类的成员函数

1实现

class Clock
{
//函数成员
public://外部接口
	void settime(int newH, int newM, int newS);
	

public :
		void ShowTime();
private://私有数据成员
	int hour, minute, second;


};
//返回类型 类名::函数名(参数)
void Clock::settime(int newH, int newM, int newS)
{
	hour = newH;
	minute = newM;
	second = newS;
}

2成员函数调用中的目的对象

如上myclock.settime,myclock就是目的对象。

3带默认形参值的成员函数

只能在类中定义

class Clock
{
//函数成员
public://外部接口
	void settime(int newH=0, int newM=0, int newS=0);
	

public :
		void ShowTime();
private://私有数据成员
	int hour, minute, second;


};

4内联成员函数

显示声明与隐式声明

class Clock
{
//函数成员
public://外部接口
	void settime(int newH=0, int newM=0, int newS=0);
	

public :
	//隐式内联函数
	void ShowTime()
	{
		cout << hour << ":" << minute << ":" << second << ":";
	};
private://私有数据成员
	int hour, minute, second;


};
//显示声明,在类定义不用加showtime
inline void	Clock::ShowTime()
{
	cout << hour << ":" << minute << ":" << second << ":";
}

4.2.5完整实例

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class h
{
public:
	//带参数的函数成员只能在类中
	void a(int h1=0, int m1=0, int s1=0);//时间置零
	//隐式内联
	void b()
	{
		cout << h << ":" << m << ":" << s << ":"<<endl;
	};
private:
	int h, m, s;//时分秒
};
//设置时间
void h ::a(int h1, int m1, int s1)
{
	h = h1;
	m = m1;
	s = s1;
}
int main()
{
	h myh;
	myh.a();//置零
	myh.b();//显示置零
	myh.a(8, 30, 30);//设置为8小时30分30秒
	myh.b();//显示



}

现象

4.3构造函数与析构函数

4.3.1构造函数 

作用

        :在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态

构造函数与类名相同

没有返回值

系统会自动生成隐含的构造函数

class a {

	a() {};//编译系统生成的隐含的默认构造函数

};

这个构造函数不做任何事情,为什么要生成?

 (还要负责基类的构造与成员对象的构造)

class a {

	a() {};//编译系统生成的隐含的默认构造函数
	a()//无参的构造函数
	{
		h = 0;
		m = 0;
		s = 0;
	}
	a(int h1, int m1, int s1);//有参的构造函数
private:
	int h, m, s;
};
//构造函数的实现
 a::a(int h1, int m1, int s1)
{
	h = h1;
	m = m1;
	s = s1;
}

4.3.2复制构造函数 

在下面三种情况调用

(1)用类的对象去初始化另一个对象
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Point
{
public:

	//(内联)构造函数
	Point(int xx = 0, int yy = 0) {
		x = xx;
		y = yy;
	}
	//复制构造函数
	Point(Point& p);
	int getx() { return x; };
	int gety() { return y; };
private:
	int x, y;
};
Point::Point(Point& p) {
	x = p.x;
	y = p.y;
}
int main()
{
	Point a(1, 5);
	//复制构造函数的调用,两个方式等效
	Point b(a);
	Point c = a;
	cout << b.getx() << endl;
	return 0;

}
(2)如果函数参数是类的对象,调用函数时,进行形参与实参的结合时
#include<iostream>
using namespace std;
class Point
{
public:

	//(内联)构造函数
	Point(int xx = 0, int yy = 0) {
		x = xx;
		y = yy;
	}
	//复制构造函数
	Point(Point& p);
	int getx() { return x; };
	int gety() { return y; };
private:
	int x, y;
};
Point::Point(Point& p) {
	x = p.x;
	y = p.y;
}
void f(Point p) {
	cout << p.getx() << endl;

}
int main() {
	Point a(1, 2);
	f(a);
	return 0;
}
(3)如果函数的返回值时类的对象,函数执行完成返回调用者时
#include<iostream>
using namespace std;
class Point
{
public:

	//(内联)构造函数
	Point(int xx = 0, int yy = 0) {
		x = xx;
		y = yy;
	}
	//复制构造函数
	Point(Point& p);
	int getx() { return x; };
	int gety() { return y; };
private:
	int x, y;
};
Point::Point(Point& p) {
	x = p.x;
	y = p.y;
}
Point g() {
	Point a(1, 2);
	return a;

}
int main() {
	Point b;
	b = g();
	cout << "b.getx=" << b.getx() << endl;
	return 0;
}

显示复制构造函数与隐式区别,可以自己控制内容,而且当类的数据成员中有指针类型时,隐式的复制构造函数只能浅复制,会带来数据安全隐患。

4.3.3析构函数

:与构造函数刚好相反,完成对象被删之前的清理工作,如果希望程序在对象被删除前自动完成某事,可以把他们写到析构函数中

4.3.4程序实例

4.4类的组合

4.4.1组合

一个类内嵌其他类的对象作为成员的情况,关系时包含与被包含

当创建类的对象时,如果这个类具有内嵌对象成员,,那么各个内嵌对象将首先被自动创建。

在创建对象时既要对本类的基本类型数据成员进行初始化,又要对内嵌对象成员进行初始化。

创造一个组合类对象时,构造函数顺序

(1)内嵌对象的构造函数,调用顺序按照内嵌对象在组合类的定义中出现的次序

(2)调用本类构造函数的函数体

析构函数刚好相反

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cmath>
using namespace std;
class Point {
public:
	Point(int xx = 0, int yy = 0) {
		x = xx;
		y = yy;
	}
	Point(Point& p);
	int gety() { return y; };
	int getx() { return x; };
private:
	int x, y;
};
Point::Point(Point& p) {
	x = p.x;
	y = p.y;
}
//类的组合
class line {
public:
	line(Point xp1, Point xp2);
	line(line& l);
	double getlen() { return len; };
private:
	Point p1, p2;
	double len;
};
//类的组合的实现
line::line(Point xp1, Point xp2):p1(xp1),p2(xp2) {
	double x = static_cast<double>(p1.getx() - p2.getx());
	double y = static_cast<double>(p1.gety() - p2.gety());
	len = sqrt(x * x + y * y);

}
//组合类的复制构造函数
line::line(line& l) :p1(l.p1), p2(l.p2) {
	len = l.len;
}

4.4.2前向引用声明

class b;//前向引用声明
class a {
public:
	void f(b b1);
};
class b {
public:
	void g(a a1);
};

 在提供一个完整的类前,不能定义该类的对象,可以使用类的对象引用或者指针

class b;//前向引用声明
class a {
public:
	void f(b b1);
	/*错误
	b类的对象在定义前被使用
	void abc() {
		x.abcd();
	}*/
	//错误,b类定义不完善
	b b1;
private:
	b& x;//b类对象的引用或指针
};
class b {
public:
	void g(a a1);
	void abcd();
};

4.5UML图形标识(略)

4.6结构体与联合体

4.6.1结构体

结构体是一种特殊形态的类,区别在于两者具有不同的默认访问控制属性:未指定访问控制属性的成员,类是private结构体是public

如果一个结构体的全部数据成员都是公共成员,并且没有用户定义的构造函数,没有基类和虚函数,可以这样赋值

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

struct student {
	int num;
	string name;
	char sex;
	int age;
};
int main()
{
	student stu = { 97001,"lin lin",'F',29 };
}

4.6.2联合体(public)

联合体的全部数据成员共享同一组内存单元。(联合体变量中的成员同时至多只有一个有意义)

联合体的对象成员,不能有自定义的构造函数,析构,重载的复制赋值运算符

联合体不能继承,不支持包含多态

一般用联合体储存一些共有数据,而不是定义函数成员

成员项具有相同的地址

无名联合体

union {
	int i;
	float f;
};
int main()
{
	i = 10;
}

使用联合体保存信息

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

class examinof {
public:
	examinof(string name, char grade)
		:name(name), mode(GRADE), grade(grade) {};
	examinof(string name, bool pass)
		:name(name), mode(PASS), pass(pass) {};
	examinof(string name, int percent)
		:name(name), mode(PERCENTAGE), percent(percent) {};
	void show();
private:
	string name;
	enum {
		GRADE,
		PASS,
		PERCENTAGE
	}mode;
	union {
		char grade;
		bool pass;
		int percent;
	};
};
void examinof::show() {
	cout << name << ":";
	switch (mode) {
	case GRADE:cout << grade;
		break;
	case PASS:cout << (pass ? "PASS" : "FAIL");
		break;
	case PERCENTAGE:cout << percent;
		break;
	}
	cout << endl;
}
int main()
{
	examinof course1("english", 'b');
	examinof source2("calculus", true);
	examinof source3("c++", 85);
	course1.show();
	source2.show();
	source3.show();
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值