C++ 类与对象

本文详细介绍了C++中的类与对象概念,包括类的定义、对象的创建、成员函数的实现方式。重点讲解了构造函数和析构函数的作用,以及如何初始化和清理对象。此外,还提到了复制构造函数、默认构造函数和析构函数的使用,以及如何通过默认或删除函数控制构造行为。最后,探讨了类的组合,展示了类的镶嵌和组合类的构造。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4.2类与对象

4.2.1类的定义

/*
class 类名{
	public:
		外部接口
	protected:
		保护型成员 
	private:
		私有成员
};
*/

class Clock{
	public:    //函数成员 
		void setTime(int newH , int newM , int newS);
		void showTime();
	private:   //数据成员 
		int hour , minute , second; 
};

4.2.3对象

	Clock myclock; //定义一个myclock对象
	myclock.setTime(2 , 3 , 4); //调用函数成员 

4.2.4类的成员函数

1、成员函数的实现

/*
返回类型 类名::函数名( )
{
	
}
*/
#include <iostream>

using namespace std;

class Clock{
	public:    //函数成员 
		void setTime(int newH , int newM , int newS);
		void showTime();
	private:   //数据成员 
		int hour , minute , second; 
};
void Clock::setTime(int newH , int newM , int newS) //成员函数在类外实现
{
	hour = newH;
	minute = newM;
	second = newS;
}
void Clock::showTime()
{
	cout << hour << ":" << minute << ":" << second << endl;
}

int main()
{
	Clock myclock; //定义一个myclock对象
	myclock.setTime(2 , 3 , 4); //调用函数成员 
	myclock.showTime();
	return 0;
} 

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

在类的成员函数中,既可以访问目的对象的私有成员,又可以访问当前类的其他对象的私成员,

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

4、内联成员函数

减少调用开销,提高执行效率,

inline void Clock::showTime()
{
	cout << hour << ":" << minute << ":" << second << endl;
}

4.3构造函数和析构函数

在定义对象的时候进行数据成员设置,称为对象的初始化,

在c++中对象的 初始化和清理工作,由两个函数,构造函数和析构函数来完成,

4.3.1构造函数

初始化程序,

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

特征:类的一个公有成员函数;函数名与类名相同,并没有返回值;

调用时无须提供参数的构造函数称为默认构造函数。

如果没有写构造函数,系统自己生成默认构造函数,若写,则不会生成,这样就不能使用无参的调用,除非在写一个构造函数(重载)。

class Clock{
	public:    //函数成员 
		Clock(){ } //默认构造函数 
};
#include <iostream>

using namespace std;

class Clock{
	public:    //函数成员 
		Clock(int newH , int newM , int newS);//构造函数 
		Clock();//函数重载,构造无参初始函数 
		void setTime(int newH , int newM , int newS);
		void showTime();
	private:   //数据成员 
		int hour , minute , second; 
};
void Clock::setTime(int newH , int newM , int newS)
{
	hour = newH;
	minute = newM;
	second = newS;
}
inline void Clock::showTime()
{
	cout << hour << ":" << minute << ":" << second << endl;
}

Clock::Clock(int newH , int newM , int newS):hour(newH),minute(newM),second(newS)
{
	/*构造函数,
	在冒号前是函数初始化列表; 
	冒号后是初始化的数据成员,每个成员名字后面紧跟括号括起来的是初始值;
	为什么不写在函数中,
	是因为,使用初始化列表对成员进行初始化,比在构造函数中用赋值语句效率高。 
	*/ 
} 
//等价于
//Clock::Clock(int n , int m , int s)
//{
//	ni = n ;
//	mi = m;
//	si = s;
 //} 


int main()
{
	Clock myclock(2 , 3 , 4); //初始化myclock对象
	myclock.showTime();
	Clock c; //myclock对象
	c.setTime(1 , 2 , 3);
	c.showTime();
	return 0;
} 

4.3.2默认构造函数

#include <iostream>
using namespace std;

class Clock{
	public:
	//1.构造方法
		Clock(int n , int m , int s);
		Clock();//无参构造方法 
		void settime(int n , int m , int s);
		void showtime();
	private:
		int ni , mi , si;
};

//2.类外实现函数内部 
void Clock::settime(int n , int m , int s)
{
	ni = n;
	mi = m;
	si = s;
}
inline void Clock::showtime()
{
	cout << ni << " " << mi << " " << si << endl;
}
//3.类外实现构造函数内部, 
Clock::Clock(int n , int m , int s): ni(n) , mi(m) , si(s)
{
}
//4.实现无参构造函数的初始化
Clock::Clock():ni(1) , mi(2) , si(3){ 
} 



int main()
{
	
	Clock m(2 , 3 , 4); //有参构造 
	m.showtime();	
	Clock c; //无参构造,已给定初始值 
	c.showtime();
	return 0;
} 
2 3 4
1 2 3

4.3.3委托构造函数

建立在构造函数上的构造函数,

委托构造函数使用类中其他的构造函数执行它自己的初始化过程,

#include <iostream>
using namespace std;

class Clock{
	public:
	//1.构造方法
		Clock(int n , int m , int s);
		Clock();//无参构造方法 
		void settime(int n , int m , int s);
		void showtime();
	private:
		int ni , mi , si;
};

//2.类外实现函数内部 
void Clock::settime(int n , int m , int s)
{
	ni = n;
	mi = m;
	si = s;
}
inline void Clock::showtime()
{
	cout << ni << " " << mi << " " << si << endl;
}
//3.类外实现构造函数内部, 
Clock::Clock(int n , int m , int s): ni(n) , mi(m) , si(s) //构造函数(被委托) 
{
}
//4.通过委托构造函数实现无参构造函数的初始化
Clock::Clock(): Clock(1 , 2 , 4){  //构造函数(委托) 
		//先执行被委托的构造函数,然后再执行委托构造函数 
		//就是通过被委托的构造函数进行初始化, 
} 

int main()
{
	
	Clock m(2 , 3 , 4); //有参构造 
	m.showtime();	
	Clock c; //无参构造,已给定初始值 
	c.showtime();
	return 0;
} 
2 3 4
1 2 4

//3.类外实现构造函数内部, 
Clock::Clock(int n , int m , int s): ni(n) , mi(m) , si(s) //构造函数(被委托) 
{
}
//4.通过委托构造函数实现无参构造函数的初始化
Clock::Clock(): Clock(1 , 2 , 4){  //构造函数(委托) 
		//先执行被委托的构造函数,然后再执行委托构造函数 
		//就是通过被委托的构造函数进行初始化, 
} 

4.3.4复制构造函数

对 对象的复制,克隆,如要复制一份a对象的副本,那么就需要新创建一个对象b然后将a的所有数据成员取出来,一一赋值给b对象,这样就很麻烦,

在此提供一种特殊的构造函数,复制构造函数,

其形参是本类的对象引用,其作用是使用一个已经存在的对象(由复制构造函数的参数指定),去初始化同类的一个新对象。

如果没有自己定义复制构造函数,系统会自动生成一个隐含的复制构造函数

隐含的复制构造函数的功能是,把初始值对象的每一个数据成员的值都复制到新建立的对象中,因此就完成了同类对象的克隆。

class Point{
	public:
		//1.构造函数
		Point(int xx ,int yy);
		//2.复制构造函数
		Point(Point &p);
		//3.get返回私有属性 
		int getX(){	return x;}
		int getY(){ return y;}
	private:
		int x , y;
};

//4.构造函数
Point::Point(int xx ,int yy){
	x = xx , y = yy;
} 
//5.复制构造函数
Point::Point(Point &p){
	x = p.x , y = p.y;
	cout << " 这是复制的对象 " << endl; 
} 

复制构造函数被调用的情况:

(1)当用类的一个对象去初始化该类的另一个对象时

int main()
{
	Point a(1 ,2);
	Point b(a); //用对象a初始化对象b
	Point c = a; //用对象a初始化对象c
	cout << b.getX() <<" " << c.getY() << endl; 
	return 0;
} 
 这是复制的对象
 这是复制的对象
1 2

(2)如果函数的形参是类的对象,调用函数时,进行形参和实参的结合

void f(Point p){
	cout << p.getX() << endl;
}

int main()
{
	Point a(1 ,2);
	f(a);
	return 0;
} 

(3)如果函数的返回值是类的对象,函数执行完成后

Point g(){
	Point a(1 , 2);
	return a; //返回时调用复制构造函数
}

int main()
{
	Point b;
	b = g();
	cout << b.getX() << endl;
	return 0;
} 
#include <iostream>
using namespace std;

class Point{
	public:
		//1.构造函数
		Point(int xx ,int yy);
		Point(){}
		//2.复制构造函数
		Point(Point &p);
		//3.get返回私有属性 
		int getX(){	return x;}
		int getY(){ return y;}
	private:
		int x , y;
};

//4.构造函数
Point::Point(int xx ,int yy){
	x = xx , y = yy;
} 
//5.复制构造函数
Point::Point(Point &p){
	x = p.x , y = p.y;
	cout <<" 这是复制的对象 " << endl; 
} 

Point g(){
	Point a(1 , 2);
	return a; //返回时调用复制构造函数
}

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

其实系统会直接自动生成隐含复制函数,不用额外定义,但如果想只复制一部分就需要自己定义。

4.3.5析构函数

用来完成对象被删除前的一些清理工作,在调用析构函数后,对象小时,对应的内存空间也被释放。

析构函数通常也是类的公有函数成员,

由类名前面加“~”构成,没有返回值,也没有任何参数,系统自动生成,

class Point{
	public:
		//1.构造函数
		Point(int xx ,int yy);
		Point(){}
		//2.复制构造函数
		Point(Point &p);
		//3.get返回私有属性 
		int getX(){	return x;}
		int getY(){ return y;}
		//4.析构函数
		~Point(){} 
	private:
		int x , y;
};

4.3.7default/delete函数

class Point{
	public:
		//1.构造函数
		Point(int xx ,int yy);
		Point() = default;//(只能)默认合成无参构造函数 
		//2.复制构造函数
		Point(Point &p) = default; //默认合成复制构造函数 
		//3.get返回私有属性 
		int getX(){	return x;}
		int getY(){ return y;}
		//4.析构函数
		~Point() = default; //默认合成析构函数 
	private:
		int x , y;
};

使用=default可以显示要求编译器自动生成默认或复制构造函数,以及析构函数。

class Point{
	public:
		//1.构造函数
		Point(int xx ,int yy);
		Point() = delete;//删除合成无参构造函数 
		//2.复制构造函数
		Point(Point &p) = delete; //删除合成复制构造函数 
		//3.get返回私有属性 
		int getX(){	return x;}
		int getY(){ return y;}
		//4.析构函数
		~Point() = default; //默认合成析构函数 
	private:
		int x , y;
};

delete,除析构函数外,用户可以随意指定为delete删除掉,

4.4类的组合

就是类的镶嵌

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

class Point{
	public:
		//1.构造函数
		Point(int xx ,int yy);
		//2.复制构造函数
	//	Point(Point &p); 
		//3.get返回私有属性 
		int getX(){	return x;}
		int getY(){ return y;}
		//4.析构函数
		~Point() = default; //默认合成析构函数 
	private:
		int x , y;
};

//4.构造函数
Point::Point(int xx ,int yy){
	x = xx , y = yy;
} 
////5.复制构造函数
//Point::Point(Point &p){
//	x = p.x , y = p.y;
//} 

//6.类的组合
class Line{
	public:
		Line(Point xp1 , Point xp2);
	//	Line(Line &l);
		double getLen(){
			return len;
		}
	private:
		Point p1, p2;
		double len;
}; 
//7.组合类的构造函数
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);
} 
////8.组合类的复制构造函数 
//Line::Line(Line & l) : p1(l.p1) , p2(l.p2){
//	len = l.len;
//}

int main()
{
	Point a(1 , 1) , b(4 ,5);
	Line line(a , b);
	cout << "The length of the line is ";
	cout << line.getLen(); 
	return 0;
} 
The length of the line is 5

复制构造函数一般程序自带

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值