类总结(二)

一.类的其它成员 :常成员 、静态成员、友元

1.常成员

(1)常成员

Ø常数据成员为使用const说明的数据成员
  如果在一个类中说明了常数据成员,那么构造函数就只能通过初始化列表对该数据成员进行初始化,而任何其他函数都不能对该成员赋值。且
被初始化后,其值不能改变。

Ø在类的成员函数说明后面可以加const关键字,则该成员函数成为常量成员函数

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;	  //错误,不能在类外修改常数据成员
struct Date { int year, month, day ; }; //结构
class Student
{ 
public:
    Student (int y,int m,int d, int num=0, sring name="no name");
    void PrintStudent()const;		//常成员函数
  private:   
    const int code;			//常数据成员
    string name;
    Date birthday;			//结构数据成员
};
带参数的构造函数完成对数据成员的初始化;
Student::Student( int y, int m, int d, int num, string name ) : code( num )
{ this->name=name;
  birthday.year=y;  
  birthday.month=m;
  birthday.day=d;
} 

(2)常对象:如果在说明对象时用const修饰,则被说明的对象为常对象。

  •    常对象的说明形式如下类名 const对象名[(参数表)]; 或者 const  类名 对象名[(参数表)];

  说明:

   (1 在定义常对象时必须进行初始化,而且不能被更新。C++不允许直接间接更改常对象的数据成员。

   (2C++规定常对象只能调用它的常成员函数、静态成员函数、构造函数(具有公有访问权限)。 

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;     //a和b为公有数据成员;
  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;
}        //编译结果为t1.a=1  t1.b=2
                    t2.a=7  t2.b=8

(3)常成员函数:在类中使用关键字const说明的函数为常成员函数

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

2.静态成员

Ø类成员冠以static声明时,称为静态成员。

Ø 静态数据成员为同类对象共享。在定义或说明前加static,如:static int s;

Ø 静态成员函数与静态数据成员协同操作。  

静态成员不属于某一个单独的对象,而是为类的所有对象所共有

静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员:保证在不依赖于某个对象的情况下,访问静态数据成员

  1. 对于类的普通数据成员,每一个对象都各自拥有一个副本。(分配不同的存储空间)
  2. 对于静态数据成员,每个类只拥有一个副本。(在静态存储区分配一个存储空间,对所有对象都是可见的)
  3. 公有访问权限的静态成员,可以通过下面的形式进行访问
  • 类名::静态成员的名字
  • 对象名.静态成员名字
  • 对象指针->静态成员的名字
  • 在静态成员函数内部,直接访问。

(1)静态数据成员声明及初始化

在类外进行静态数据成员的声明:类型 类名::静态数据成员[=初始化值];   //必须进行声明

  • 不能在成员初始化列表中进行初始化
  • 如果未进行初始化,则编译器自动赋初值(默认值是0
  • 初始化时不能使用访问权限

(2)静态成员函数

  • 静态函数仅可以访问静态成员,主要用来访问同一类中的静态数据成员。

    静态成员函数不访问类中的非静态数据成员。如有需要,只能通过对象名(或指向对象的指针)访问该对象的非静态成员。

  • 静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。
  • 静态成员函数没有this指针,只能对静态数据操作

定义静态成员函数的格式如下:  static  返回类型  静态成员函数名(参数表); 在类外定义时不用static前缀。

    与静态数据成员类似,调用公有静态成员函数的一般格式有如下几种:

   类名::静态成员函数名(实参表)

   对象. 静态成员函数名(实参表)

   对象指针->静态成员函数名(实参表)

说明:

  • 私有静态成员函数不能在类外部或用对象访问。
  • 可以在建立对象之前处理静态数据成员。
  • 编译系统将静态成员函数限定为内部连接(在其他文件中不可见)

二.友元函数

如果在本类A以外的其他地方定义了一个函数函数B),这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数,在类体中用friend对其函数B进行声明,此函数就称为本类A的友元函数。友元函数函数B可以访问这个类A中的私有成员。

三.类的包含(类的组合)

Ø当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化语法形式

构造函数 ( 形参表 ) : 对象成员1(形参表 ) , … , 对象成员n (形参表 )

(1)对象成员的初始化

  • 出现成员对象时,该类的构造函数要包含对象成员的初始化。如果构造函数的成员初始化列表没有对成员对象初始化时,则使用成员对象的无参(缺省构造函数。
  • 建立一个类的对象时,要先执行成员对象自己的构造函数,再执行当前类的构造函数。
  • 成员对象的构造函数调用次序和成员对象在类中的说明次序一致(声明顺序为:a1b1b2),与它们在成员初始化列表中出现的次序无关(初始化列表顺序为:b1b2a1)。

  • 析构函数的调用顺序相反

四.对象数组:指每一数组元素都是对象的数组。

  1.    定义一个一维对象数组的格式如下  类名  数组名[下标表达式]; 
  2. 对象数组的初始化:

(1):当对象数组所属的类中包含带参的构造函数,可用初始化列表完成对象数组的初始化。

#include <iostream>
using namespace std;
class Point
{
	int x, y;
public:
	Point(){x=y=0;}
	Point(int xi,int yi)
	{ x=xi;y=yi; }
	Point (int c)
	{ x=y=c; }
	void Print()
	{	cout<<"("<<x<<","<<y<<")";	}
};
int main(){      //熟知数组的几种方式;
	Point p1[4];
	Point p2[4]={5,6,7,8};
	Point p3[4]={Point(9,10),Point(11,12),Point(13,14),Point(15,16)};
	Point p4[4]={Point(17,18),Point(10,20)};
	Point p5[2][2]={21,22,Point(23,24)};
	for(int i=0;i<4;i++)	p1[i].Print();
	cout<<endl;
	for(int i=0;i<4;i++)  p2[i].Print();
	cout<<endl;
	for(int i=0;i<4;i++)  p3[i].Print();
	cout<<endl;
	for(int i=0;i<4;i++)  p4[i].Print();
	cout<<endl;
	for(int i=0;i<2;i++)
	for( int j=0;j<2;j++)	p5[i][j].Print();
	cout<<endl;
	return 0;
}
编译结果为:
(0,0)(0,0)(0,0)(0,0)
(5,5)(6,6)(7,7)(8,8)
(9,10)(11,12)(13,14)(15,16)
(17,18)(10,20)(0,0)(0,0)
(21,21)(22,22)(23,24)(0,0)

(2):当对象数组所属的类中包含无参的构造函数,也可以先定义,再给每个数组元素赋值

int main()
{
	Point p1[4];
    p1[0]=Point(1,1);
}

(3): 当对象数组所属的类中包含单个参数的构造函数,可简写。

  eg:Point p2[4]={5,6,7,8};

  //Pointp2[4]={Point(5), Point(6), Point(7), Point(8)};

(4)无法通过初始化成员列表对对象数组进行初始化

错误举例:

class A
{
public:
	A(int i = 0):x(i) {}
	int x;
};
class B
{
public:
	B():a[0](0),a[1](1) {}  // error C2059: 语法错误 : “[”
	A a[2];
};

正确举例:

class B
{
public:
	B()   //成员对象数组已经通过A的默认构造函数初始化了,下面是进行赋值
	{
		a[0] = A(0);
		a[1] = A(1);
	}
	A a[2];
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值