类与对象(第二部分)

this指针(this表示当前对象)
显式引用 this指针的三种情况
(1)在类的非静态成员函数中返回类对象本身或对象的引用的时候,直接使用 return *this,返回本对象的地址时,return this。

#include <iostream>
#include <string>
using namespace std;
class Person{
public:
	Person(string n, int a)	{
		name = n;    //这里的 name 等价于this->name
		age = a;      //这里的 age 等价于this->age
	}
	int get_age(void) const{  return age;  }
	Person& add_age(int i)	{age += i;    	return *this;  //返回值为当前对象的引用	}
private:
	string name;
	int age;
};
int main()
{
	Person Li("Li", 20);
	cout<<"Li age = "<< Li.get_age()<<endl;
	cout<<"Li add age = "<< Li.add_age(1).get_age()<<endl;  
		 //增加1岁的同时,可以对新的年龄直接输出,Li返回值为当前对象的引用();
	return 0;
}
程序执行结果为:
	Li age = 20
	Li add age = 21

(2)当参数与成员变量名相同时,如this->x = x,不能写成x = x。

#include <iostream>
using namespace std;
class Point
{
public:
	int x;
	Point ():x(0){}
	Point (int a){  x=a;  }
	void print(){   cout<<"x = "<<x<<endl;  }
	void set_x(int x){  x = x;  }
};
int main(){
	Point pt(5);
	pt.set_x(10);
	pt.print();
	return 0;
}
程序执行结果为:
x = 5
若将set_x函数改为:
	void set_x(int x)	{	this->x = x;	}
程序执行结果为:
	x = 10

(3)避免对同一对象进行赋值操作,判断两个对象是否相同时,使用this指针。

#include <iostream>
using namespace std;
class Location 
{
     int X,Y;  //默认为私有的
 public:
     void init(int x,int y) { X =x; Y = y;};
     void assign(Location& pointer);//
     int GetX(){ return X; }
     int GetY(){ return Y; }
};
void Location::assign(Location& pointer)
{
    if(&pointer!=this) //同一对象之间的赋值没有意义,所以要保证pointer不等于this
    {        X=pointer.X;        Y=pointer.Y;    }
}
 int main(){
    Location x;
    x.init(5,4);
    Location y;
    	y.assign(x);
    	cout<<"x.X = "<< x.GetX()<<" x.Y = "<<x.GetY();
    	cout<<"y.X = "<< y.GetX()<<" y.Y = "<<y.GetY();
    	return 0;
}

复制构造函数
语法形式
类名 :: 类名(const 类名 & 引用名 , …);
(形参)参数是同类对象,
要求有一个类类型的引用参数。

浅复制:
在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,即:对于复杂类型的数据成员只复制了存储地址而没有复制存储内容
深复制:
一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源
定义:类名::类名([const] 类名 &对象名);

类的其他成员

常成员
静态成员
友元(破坏了封装,不建议使用)
1 常成员
(1)常数据成员
常数据成员是指数据成员在实例化被初始化后,其值不能改变
如果在一个类中说明了常数据成员,那么构造函数就只能通过初始化列表对该数据成员进行初始化,而任何其他函数都不能对该成员赋值。

#include<iostream>
using namespace std;
class Mclass
{ public :
      int k;
      const int M;		//说明常数据成员
      Mclass() : M(5) { } 	//用初始式对常数据成员赋值
      void testFun()
       { //M++;	 	//错误,不能在成员函数中修改常数据成员
           k++;		//可以修改一般数据成员
       }
 } ;
 int main()
{ Mclass t1, t2;
   t1.k=100;	
   //t1.M=123;	//错误,不能在类外修改常数据成员
   cout<<"t1.k="<<t1.k<<'\t'<<"t1.M="<<t1.M<<endl;
   t2.k=200;   t2.testFun();
   cout<<"&t1.M="<<&t1.M<<endl;
   cout<<"t2.k="<<t2.k<<'\t'<<"t2.M="<<t2.M<<endl;
   cout<<"&t2.M="<<&t2.M<<endl;
}
#include<iostream>
#include<cstring>
using namespace std;
struct Date { int year, month, day ; }; //结构
class Student
{ public:
    Student (int y,int m,int d, int num=0, string name="no name");
    void PrintStudent()const;		//常成员函数
  private:   
    const int code;			//常数据成员
    string name;
    Date birthday;			//结构数据成员(数据对象)
};

(2)常对象:
说明形式如下:
类名 const 对象名[(参数表)];
或者
const 类名 对象名[(参数表)];
在定义常对象时必须进行初始化,而且不能被更新
说明:
(1)C++不允许直接或间接更改常对象的数据成员。
(2)C++规定常对象只能调用它的常成员函数、静态成员函数、构造函数(具有公有访问权限)。

class T_class
{ public:
       int a, b;
  T_class( int i, int j )  { 
      a=i; b=j; 
   }
} ;
int main()
{ const T_class t1( 1, 2 );	
  T_class t2( 3, 4 );
  //t1.a=5;
  //t1.b=6;不能更改
   t2.b=8;
 t2.a=7;
cout<<"t1.a="<<t1.a<<'\t'<<"t1.b="<<t1.b<<endl;
  cout<<"t2.a="<<t2.a<<'\t'<<"t2.b="<<t2.b<<endl;
}

(3)常成员函数:
在类的成员函数说明后面可以加const关键字,则该成员函数成为常量成员函数(对数据成员只读不写)
格式如下:
类型说明符 函数名(参数表) const;
const是函数类型的一个组成部分,因此在函数的实现部分也要带关键字const
常成员函数不能更新对象的数据,也不能调用非const修饰的成员函数(静态成员函数、构造函数除外)
(只读不写)。

void  constFun ( ) const
         { x ++ ; y ++ ; }//非法

2,静态成员:(即类成员)
静态数据成员为同类对象共享
静态成员函数与静态数据成员协同操作
(1)静态数据成员:
公有访问权限的静态成员,可以通过下面的形式进行访问:
类名::静态成员名字
对象名.静态成员名字
对象指针->静态成员名字
在静态成员函数内部,直接访问。
静态数据成员声明及初始化:
类型 类名::静态数据成员[=初始化值]; //必须进行声明
不能在成员初始化列表中进行初始化

class  X {  char  ch ;  static  int s ;... };
  int X :: s = 0 ;
  X  a , b , c , d ;

如果未进行初始化,则编译器自动赋初值(默认值是0)

例题:

某商店经销一种货物,货物成箱进,成箱卖出,购进和卖出都是以重量为单位(每箱的重量不同),商店需要记录下存货的总重量。
分析:
定义一个货物类,表示一箱货物,类中包含
私有成员 weight
一个静态数据成员total_weight;
定义in函数,表示进货,进货时total_weight的值增加
定义out函数,表示出货,出货时total_weight的值减少

#include <iostream>
using namespace std;
class Goods{
	int weight;
public:
    static int total_weight;//类对象
	Goods(int x):weight(x){}
	void in()	{total_weight=total_weight+weight;	}
	void out(){total_weight=total_weight-weight;	}
    void display_store(){ cout<<total_weight<<endl;}
	};
int Goods::total_weight=0;
void display_store(){ cout<<Goods::total_weight<<endl;}
int main(){
	Goods g1(10)g2(20);
	g1.in();	
	g2.in();
	g1.display_store();	
	g2.display_store(); 
	display_store();
	g1.out(); 	 
	g1.display_store();	
	display_store();
	return 0;
}

(2)静态成员函数
静态成员函数和静态数据成员都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。
静态成员函数没有this指针,只能对静态数据操作
定义静态成员函数的格式如下:
static 返回类型 静态成员函数名(参数表);
调用公有静态成员函数的一般格式:
类名::静态成员函数名(实参表)
对象. 静态成员函数名(实参表)
对象指针->静态成员函数名(实参表)
说明:
(1)静态成员函数在类外定义时不用static前缀。
(2)静态成员函数主要用来访问同一类中的静态数据成员。
(3) 私有静态成员函数不能在类外部或用对象访问。
(4)可以在建立对象之前处理静态数据成员。
(5)编译系统将静态成员函数限定为内部连接(在其他文件中不可见)。
(6)静态成员函数中是没有this指针的。
(7)静态成员函数不访问类中的非静态数据成员。如有需要,只能通过对象名(或指向对象的指针)访问该对象的非静态成员。

3.友元函数(破坏封装)
(1)友元函数
如果在本类(类A)以外的其他地方定义了一个函数(函数B)
类体中用friend对其(函数B)进行声明,此函数就称为本类(类A)的友元函数。

#include<iostream>
using namespace std;
class Boat{
      int weight;
public:
   Boat(){weight=0;}
   Boat(int w):weight(w){}
   friend void display_weight(Boat &a);
};
void display_weight(Boat &a){
    cout<<a.weight<<endl;}
int main(){
    Boat b(100);
    display_weight(b);
     return 0;
}

(2)友元类
若F类是A类的友元类,则F类的所有成员函数都是A类的友元函数
声明:friend class 类名;

#include<iostream>
using namespace std ;
class A
{ friend class B ;
   public :
       void  Display() 
	{ cout << x << endl ; } ;
   private :
	int  x ;
} ;
class  B
{ public :
       void Set ( int i ) { Aobject . x = i ; } 
       void Display ()  { Aobject . Display () ; } 
   private :
	A  Aobject ;
} ;
int main()
{ B  Bobject ;
   Bobject . Set ( 100 ) ;
   Bobject . Display () ;
}

4.类的组合
当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化语法形式。
构造函数 ( 形参表 ) : 对象成员1(形参表 ) , … , 对象成员n (形参表 ) ;

#include<iostream>
using namespace std;
class A
{ public:
     A(int x):a(x){ }
     int a ;
};
class B
{ public:
     B( int x, int y ) : aa(x)  { b = y ; }
     //类类型初始化列表
     //成员对象的构造函数调用次序和成员对象在类中的说明次序一致,与它们在成员初始化列表中出现的次序无关
     void out() { cout<<"aa = "<<aa.a<<endl<<"b = "<<b<<endl ; }
  private:
     int b ;
     A aa ;
} ;
int main()
{ B objB( 3, 5 ) ;
  objB.out() ;
}

class Score
{
public:
    Score(float c, float e, float m );
    Score();
    void show();
    void modify(float c, float e, float m);
private:
    float computer;
    float english;
    float mathematics;
};
class Student
{
private:
    string name;
    string stu_no;
    Score score1;
public:
    Student(string name1, string stu_no1, float s1, float s2, float s3):score1(s1,s2,s3){
        name=name1;
         stu_no=stu_no1;
}
~Student();
    void modify(string name1, string stu_no1, float s1, float s2, float s3);
    void show();
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值