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
复制构造函数一般程序自带