c++笔记(6):类、对象、构造函数、析构函数、静态成员、友元、类包含

1.
类(Class)是面向对象程序设计(OOP)实现信息封装的基础。类是用户定义类型,也称为类类型,每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。
面向对象编程的程序基本单位是类,类是数据和操作数据的函数的封装,类的对象使用自己的方法完成对数据的操作,类可以隐藏数据和操作细节,对象通过类接口与外部通信。
类中定义成员函数:
class Tdate
{  public:
        void  Set(int m, int d, int y )  { month = m ;  day = d ; year = y ; }
        int  IsLeapYear()
           { return ( year%4 == 0 && year%100 != 0 )||( year%400 == 0); }
        void  Print()  { cout << year << "." << month << "." << day << endl ; }
   private:
        int  month;    int  day;    int  year;
};
类外定义成员函数:
void Tdate :: Set(int m, int d, int y )   { month = m ;  day = d ; year = y ; }
int  Tdate :: IsLeapYear()    { return ( year%4 == 0 && year%100 != 0 )||( year%400 == 0); }
void Tdate :: Print()  { cout <

2.
class ,struct,union都可以定义一个类:
class 缺省说明时,其成员被认为是私有的
struct 若不特别指出,其所有成员都是公有的
union 其所有成员都是公有的,且不能更改
成员的性质由关键字public、protected、private 决定
public      公有公有段的成员是提供给外部的接口
protected     保护 保护段成员在该类和它的派生类中可见
private      私有私有段成员仅在类中可见
各段中既可以包含数据成员,也可以包含成员函数
类说明的一般形式为: 
class 类名
{ public:
公有段数据成员和成员函数 ;
   protected: 
保护段数据成员和成员函数 ;
   private:
私有数据成员和成员函数 ;
} ; 

注:

<1>允许已定义类名出现在类的说明中,但不能出现无穷递归结构

<2>类可以无名,用来直接声明对象
<3>类是一个程序包。可以只有数据成员或只有成员函数,或者为空。(空的类占1个字节) 

3.

访问对象成员

公有成员是提供给外部的接口,类外用“ . ” 和 “ -> ” 运算符访问对象成员 
//例6-4 用指针访问对象成员 
#include
using namespace std ;
class  Tclass
{  public :
   int  x, y ;
   void  print() { cout << x << "," << y << endl ; } ;
} ;
int add( Tclass * ptf )  { return ( ptf->x + ptf->y ) ; } 
int main()
{ Tclass  test,  * pt = new(Tclass) ; //建立动态对象	
   pt->x = 100 ;    pt->y = 200 ;//用指针访问对象成员
   pt->print() ;
   test.x = 150 ;    test.y = 450 ;
   test.print() ;
   cout << "x+y=" << add(&test) ;//向函数传递对象地址 
}


4.

this指针

成员函数隐含定义this指针,接收调用对象的地址 
#include 	//例6-5
using namespace std ;	
class  Simple
{   int  x, y ;
  public :
     void setXY ( int a, int b) { x = a ;  y = b ; }//void setXY (int a,int b,Simple * const this){this->x = a;this->y = b;}this 指针不能显式声明,可以显式使用
     void printXY() { cout << x << "," << y << endl ; } ;
} ;
int main()
{ Simple obj1, obj2, obj3 ; 
   obj1 . setXY ( 10, 15 ) ;//相当于obj1 . setXY ( 10, 15, &obj1 ),
   obj1 . printXY () ;
   obj2 . setXY ( 20, 25 ) ;
   obj2 . printXY () ;
   obj3 . setXY ( 30, 35 ) ;
   obj3 . printXY () ;
}

5.

构造函数和析构函数:

构造函数是用于创建对象的特殊成员函数,当创建对象时,系统自动调用构造函数
构造函数的作用是:为对象分配空间;对数据成员赋初值;请求其他资源
没有用户定义的构造函数时,系统提供缺省版本的构造函数
构造函数名与类名相同,构造函数可以重载
构造函数可以有任意类型的参数,但没有返回类型

析构函数是用于取消对象的成员函数
当一个对象作用域结束时,系统自动调用析构函数
析构函数的作用是进行清除对象,释放内存等
没有用户定义析构函数时,系统提供缺省版本的析构函数
析构函数名为:~类名
析构函数没有参数,也没有返回类型
class  AA 
      { public: 
AA() { …… }
          ~AA() { …… }
          …… 
      } ;
        …… 
    void test()  
      { int  x , y ;
         AA  t1,  t2 ;// 两次调用构造函数,创建对象
          …… 
         return ;//两次调用析构函数,撤消对象
       }// 变量 x, y 生存期结束
#include//例6-7
using namespace std ;	
class Date
{ public:
    Date(int,int,int) ;   	     ~Date() ;
    void SetDate( int y, int m, int d ) ;
    void IsLeapYear() ; 	void PrintDate() ;
  private:    int year, month, day ;
} ;
/*Date:: Date(int y, int m, int d) : year(y), month(m), day(d)
{ cout<

//例6-8  对象成员初始化 
#include
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 ( ) ;
  } 

6.

重载构造函数

若类 X 具有一个或多个构造函数,创建类 X 的对象时,根据参数的类型和个数进行匹配
构造函数可以使用缺省参数,但谨防二义性
class  X
{ public:
    X ( ) ;
    X( int  i = 0 ) ;
    ...
} ;
int main ()
{ X  one(10) ;        // 正确,调用 X::X(int  i= 0) 
  X  two ;         //错误,有二义性。调用 X::X(),还是调用 X::X(int  i= 0) ?		
}

7.

复制构造函数

复制构造函数用一个已有同类对象的数据对正在建立的对象进行数据初始化
C++为类提供默认版本的复制构造函数,程序员可以定义用户版本的复制构造函数 
语法形式: 类名 :: 类名(const  类名  &  引用名  ,  …);//保护实参对象只读
//(1)用已有对象初始化新创建对象 
#include
using namespace std ;
class  Location 
{ public :
      Location ( int xx = 0, int yy = 0 )  { X = xx ;  Y = yy ; }
      Location ( const Location  & p ) 
       { X = p.X ;  Y = p.Y ;   cout << "Copy_constructor called." << endl ; }
      int GetX() { return  X ; }
      int GetY() { return  Y ; }
  private :  int  X ,  Y ;
} ;
int main()
{ Location  A ( 1, 2 ) ;
   Location B ( A ) ;	//或者Location B=A,都是调用复制构造函数,;	
   cout << "B : " << B.GetX() << " , " << B.GetY() << endl ;
} 

//(2)函数的类类型实参初始化形参时,要调用复制构造函数 
#include
using namespace std ;
class Location 
{ public:
       Location( int xx = 0 , int yy = 0 ) 
           { X = xx ;  Y = yy ;  cout << "Constructor Object.\n" ;  }
      Location( const Location & p ) 	    //复制构造函数
       { X = p.X ;  Y = p.Y ;   cout << "Copy_constructor called." << endl ;  }
     ~Location() { cout << X << "," << Y << " Object destroyed." << endl ; }
     int  GetX () { return X ; }		int GetY () { return Y ; }
  private :   int  X , Y ;
} ;
void f ( Location  p )    { cout << "Funtion:" << p.GetX() << "," << p.GetY() << endl ; }
int main()
   {  Location A ( 1, 2 ) ; 
       f ( A ) ;
  } 

//(3)函数返回类类型时,通过复制构造函数建立临时对象 
#include
using namespace std ;
class  Location
{ public :
    Location ( int xx = 0, int yy = 0 ) 
        { X = xx ; Y = yy ;
          cout << "Object constructed." << endl ;
        }
    Location ( const Location & p ) 
        { X = p.X ; Y = p.Y ;
           cout << "Copy_constructor called." << endl ; 
        }
    ~Location() 
       { cout << X << "," << Y << " Object destroyed." << endl ; } 
     int GetX() { return X ; } 	
     int GetY() { return Y ; }
  private :  int  X, Y ;
} ;
Location g()
    { Location A ( 1, 2 ) ;
       return A ;//把局部对象A复制到匿名对象
    }
int main() 
   { Location  B ;
      B = g() ;//执行默认赋值重载运算,匿名对象数据赋给对象B
   }//析构过程有三步,先析构匿名对象,再析构对象A,B


8.

浅复制和深复制

默认复制构造函数可以完成对象的数据成员值简单的复制,对象的数据资源是由指针指示的堆时,默认复制构造函数仅作指针值复制
//例6-14 修改程序    
#include
using namespace std ;
#include
class name
{ public :
       name(char *pn) ;
       name::name(const name &Obj);
       ~ name() ;
   protected : 
       char *pname ;       int size ;
} ;
name :: name(char *pn)
 { cout <<" Constructing " << pn << endl ;
    pname = new char[strlen(pn)+1] ;
    if (pname!=0) strcpy(pname,pn) ;
    size = strlen(pn) ;
 } 
name::name(const name &Obj) //如果不用复制构造函数,会导致两个对象共享一个内存,操作异常
{ cout << " Copying " << Obj.pname << " into its own block\n" ;
  pname = new char[strlen(Obj.pname)+1] ;
  if (pname!=0) strcpy(pname, Obj.pname) ;
  size = Obj.size ;
}
name :: ~ name()
{ cout << " Destructing " << pname << endl ; 
   delete  pname ;//或者delete []pname
   size = 0 ;
}
int main() 
 { name Obj1("NoName") ;
    name Obj2 = Obj1 ;//调用复制构造函数
 }

9.
类定义中除了一般指定访问权限的成员,还可以定义各种特殊用途的成员:常成员,静态成员,友元
常数据成员是指数据成员在实例化被初始化后约束为只读。
常成员函数是指成员函数的this指针被约束为指向常量的常指针,函数体内不能修改数据成员的值。 
例6-15  由构造函数直接用常量初始化常数据成员
#include
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="<
//常成员函数
#include
using namespace std ;
class  Simple
{   int  x, y ;
  public :
     void setXY ( int a, int b) { x = a ;  y = b ; }
     void printXY() { cout << x << "," << y << endl ; } ;
    void  constFun () const//常成员函数不可修改数据成员
    { 
				//x ++ ; 
				//y ++ ; //常成员函数修改数据成员非法

			  cout<

10.

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

静态数据成员为同类对象共享,静态成员函数与静态数据成员协同操作
//例6-19  私有静态数据成员的说明和初始化 
#include
using namespace std ;
class  counter
{     static  int  num ;
  public :
      void  setnum ( int i ) { num = i ; }	
      void  shownum() { cout << num << '\t' ; }
} ;
int  counter :: num = 0 ;	
int main ()
{  counter  a , b ;
    a.shownum() ;    b.shownum() ;
    a.setnum(10) ;
    a.shownum() ;    b.shownum() ;//同一个静态数据成员
    cout<


// 例6-20   使用公有静态数据成员 
#include
using namespace std ;
class  counter
{ public :
      counter (int a) { mem = a; }
      int mem;		//公有数据成员
     static  int  Smem ;	//公有静态数据成员
} ;
int  counter :: Smem = 1 ;	//初始值为1
int main()
{  counter c(5);
    int i ;
    for( i = 0 ; i < 5 ; i ++ )
      { counter::Smem += i ;
         cout << counter::Smem << '\t' ;//访问公有静态数据成员counter::Smem
       }
    cout<
静态成员函数:静态成员函数数冠以关键字static

静态成员函数没有this指针,只能对静态数据操作
在类外调用静态成员函数用“类名 :: ”作限定词,或通过对象调用
class X
{ public :
     static  void StaFun ( int i ,  X *ptr ) ; 
     int  staDat ;
} ; 
void  X :: StaFun ( int i ,  X * ptr ) 
{  
staDat = i ;    // 错误,不知道staDat引自哪一个对象?应该用ptr -> staDat = i 
} 

11.

友元:友元是对类操作的辅助手段,友元能够引用类中本来被隐蔽的信息,使用友元目的是基于程序的运行效率

运算符重载的某些场合需要使用友元
友元可以是函数,也可以是类
友元关系是非传递的。即 Y 是 X 的友元,Z 是 Y 的友元,但 Z 不一定是X的友元
class  A
{
private:
	int i;
	friend void FriendFun(A*,int);//说明语句的位置与访问描述无关
public:
	void MemberFun(int);
}
void FriendFun(A*ptr,int x)
{
	ptr->i=x;//友元函数通过对象参数访问私有数据成员
}
void A:MemberFun(int x)
{
	i=x;
}
友元类:若F类是A类的友元类,则F类的所有成员函数都是A类的友元函数
友元类通常设计为一种对数据操作或类之间传递消息的辅助类 
#include
using namespace std ;
class A
{ friend class B ;//类 B 是类 A 的友元
   public :
       void  Display() { cout << x << endl ; } ;
   private :
	int  x ;
} ;
class  B
{ public :
       void Set ( int i ) { Aobject . x = i ; } //通过类成员访问A类的私有数据成员
       void Display ()  { Aobject . Display () ; } //通过类成员调用A类的成员函数
   private :
	A  Aobject ;//类 B 的 A 类数据成员
} ;
int main()
{ B  Bobject ;
   Bobject . Set ( 100 ) ;
   Bobject . Display () ;
}


12.

类的包含

类的包含(称为has A)是程序设计中一种软件重用技术。即定义一个新的类时,通过编译器把另一个类 “抄”进来。 
当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化语法形式。
//例6-24 用类包含求计算两点之间的距离
#include
#include
using namespace std;
class  Point 
{ public:
       Point( int xi=0, int yi=0 ) { x = xi; y = yi; }
       int GetX()  {  return x;  }
       int GetY()  {  return y;  }
  private:  int x;  int y;
};
class Distance 
{ public:
      Distance( Point xp1, Point xp2 );
      double GetDis()  {  return dist;  }
  private:
     Point p1, p2;
     double dist;
};
//构造函数计算距离
Distance::Distance( Point xp1, Point xp2 ) : p1( xp1 ), p2( xp2 )
{ double x = double(p1.GetX() - p2.GetX());
  double y = double(p1.GetY() - p2.GetY());
  dist = sqrt(x * x + y * y);
}
int main()
{ Point mp1( 5, 10 ), mp2( 20, 30 ) ;
   Distance mdist( mp1, mp2 ) ;
   cout<<"The distance is "<

备注:
#include		
using namespace std ;	
class Date
{ public:
    Date(){cout<<"HELLO WORLD"<

你可能感兴趣的:(c++笔记(6):类、对象、构造函数、析构函数、静态成员、友元、类包含)