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 <
注:
<1>允许已定义类名出现在类的说明中,但不能出现无穷递归结构
<2>类可以无名,用来直接声明对象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.
构造函数和析构函数:
构造函数是用于创建对象的特殊成员函数,当创建对象时,系统自动调用构造函数#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.
复制构造函数
复制构造函数用一个已有同类对象的数据对正在建立的对象进行数据初始化//(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 ;//调用复制构造函数
}
例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<
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.
友元:友元是对类操作的辅助手段,友元能够引用类中本来被隐蔽的信息,使用友元目的是基于程序的运行效率
运算符重载的某些场合需要使用友元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"<