这次要讨论的是类的相关知识。类是C++最重要的特性。一个类的定义包含了两部分:类声明与类函数定义。
///类的实现
#include<iostream>
using namespace std;
class item//类声明,关键词class
{
int number;//类变量声明,默认为私有
float cost;//私有成员不可被类外访问
public:
void getdata(int a,float b);//函数声明
void putdata(void)//类内的函数定义,需要注意,当函数定义于类内时,它变成一个内联函数,因此只有小函数才在类内定义
{
cout<<number<<endl;
cout<<cost<<endl;//改函数的作用是,显示私有变量的值
}
};//类的声明以分号结尾
void item::getdata(int a,float b)//类外的函数定义,格式:返回类型 类名::函数名(参数声明){ 函数体 }
{
number=a;
cost=b;//该函数的作用是,为类中的数据变量赋值
}
int main()
{
item x;//创建类对象x
cout<<"\nobject x"<<endl;
x.getdata(100,299.95);//利用类对象,使用点操作符(.)对成员函数进行调用
x.putdata();//类的成员函数只能通过该类的对象调用,并且要使用点操作符
item y;//创建类对象y
cout<<"\nobject y"<<endl;
y.getdata(200,175.50);
y.putdata();
return 0;
}
该程序点明了类的基本运用及注意点,要定义类的时候参照以上程序就能基本实现了。
/程序2.成员函数的嵌套:成员函数被同类的另一个成员函数调用
//一般情况下,类内所有数据项声明为私有,所有函数声明为公共
//但对于声明为类的私有成员函数而言,只能被类的另一个成员函数调用
#include<iostream>
using namespace std;
class set//类set的声明,改类包含两个整型私有变量即三个成员函数
{
int m,n;
public:
void input(void);//为类的两个私有数据赋值
void display(void);//显示数据
int largest(void);//获取较大的一个数
};
int set::largest(void)//类set成员函数largest的定义
{
if(m>=n)
return(m);
else
return(n);
}
void set::input(void)//类set成员函数input的定义
{
cout<<"Input values of m and n:"<<endl;
cin>>m>>n;
}
void set::display(void)//类set成员函数set的定义
{
cout<<"Largest values="<<largest()<<endl;//调用成员函数
}
int main()
{
set A;//创建类set的一个对象A
A.input();
A.display();
return 0;
}
在上述程序中,类的成员函数display()中嵌套调用类的成员函数largest(),这说明了成员函数可被同类的另一个成员函数调用。
///程序3.类内数组的使用--处理商品列表
//本程序执行如下任务:添加商品、删除某个商品、显示所有商品价格总和、显示所有商品的详细信息
#include<iostream>
using namespace std;
const int m=50;//设置常数m,表示最多能输入的商品数
class ITEMS//商品类ITEMS声明
{
int itemCode[m];//商品的条形码的类内数组
float itemPrice[m];//商品的价格的类内数组
int count;//当前记录的商品数
public:
void CNT(void){count=0;}//初始化商品数
void getitem(void);
void displaySum(void);
void remove(void);
void displayItems(void);
};
void ITEMS::getitem(void)//添加商品(表示进货)
{
cout<<"Enter item code:";
cin>>itemCode[count];
cout<<"Enter item cost:";
cin>>itemPrice[count];
count++;
}
void ITEMS::displaySum(void)//显示所有商品价格总和
{
float sum=0;
for(int i=0;i<count;i++)
sum +=itemPrice[i];
cout<<"Total value:"<<sum<<endl;
}
void ITEMS::remove(void)//删除某个商品(将其价格设为0,表示缺货)
{
int a;
cout<<"Enter item code:";
cin>>a;
for(int i=0;i<count;i++)
{
if(itemCode[i]==a)
itemPrice[i]=0;
}
}
void ITEMS::displayItems(void)//显示所有商品的详细信息
{
cout<<"Code Price"<<endl;
for(int i=0;i<count;i++)
{
cout<<"\n"<<itemCode[i]
<<" "<<itemPrice[i];
}
cout<<endl;
}
int main()
{
ITEMS order;
order.CNT();
int x;
do
{
cout<<"\nYou can do the following;Enter appropriate number"<<endl;//提示命令操作
cout<<"1.Add an item"<<endl;
cout<<"2.Display total value"<<endl;
cout<<"3.Delete an item"<<endl;
cout<<"4.Display all items"<<endl;
cout<<"5.Quit"<<endl;
cout<<"What is your option?"<<endl;
cin>>x;
switch(x)//利用switch语句来进行操作命令的选择
{
case 1: order.getitem();break;//注意,使用switch时,每一种情况下都要用一个“break”
case 2: order.displaySum();break;
case 3: order.remove();break;
case 4: order.displayItems();break;
case 5: break;
default : cout<<"Error in input;try again"<<endl;//必须要有“default”语句,对不满足情况的进行处理
}
}
while(x!=5);//使用do...while来控制循环的结束,即当x=5时结束程序运行
return 0;
}
上述程序通过定义一个类,该类使用数组作为数据成员,实现了对商品的诸多细节性操作,如添加商品、删除商品、打印订单的总价钱等。
/程序4.静态类成员
#include<iostream>
using namespace std;
class item
{
static int count;//静态类成员的声明,关键词static
int number;
public:
void getdata(int a)
{
number=a;
count++;
}
void getcount(void)
{
cout<<"count:";
cout<<count<<endl;
}
};
int item::count;//静态数据成员的定义
//每个静态成员变量的类型和作用域都定义于类的定义之外
int main()
{
item a,b,c;
a.getcount();
b.getcount();
c.getcount();
a.getdata(100);
b.getdata(200);
c.getdata(300);
cout<<"After reading data"<<endl;
a.getcount();
b.getcount();
c.getcount();//三个对象共享了一个count(此为静态变量),所以最后输出值都相等
return 0;
}
静态类成员的性质:1.被创建时,初始化为0;2.静态成员只有一个实例,无论创建多少泪对象,它们都共享这一静态成员变量;//3.静态成员只在类内可见,其生存期为程序整个执行期。
/程序5.静态成员函数
#include<iostream>
using namespace std;
class test
{
int code;
static int count;//声明静态成员变量
public:
void setcode(void)
{
code=++count;
}
void showcode(void)
{
cout<<"object number:"<<code<<endl;
//cout<<"object number:"<<count<<endl;
}
static void showcount(void)//静态成员函数的定义
{
cout<<"count:"<<count<<endl;//在这里,静态函数只能调用静态成员变量count,若调用code则出错
}
};
int test::count;//静态数据成员的定义
int main()
{
test t1,t2;//创建类对象t1,t2
t1.setcode();//调用类成员函数setcode
t2.setcode();
test::showcount();//静态成员函数的调用,使用类名调用
test t3;
t3.setcode();
test::showcount();
t1.showcode();
t2.showcode();
t3.showcode();//三个变量各有自已的code副本,所以最后值各不相同
return 0;
}
静态成员函数的特性:1.只能访问类内声明的其它静态成员;2.使用类名调用静态成员函数
/程序6.对象数组
#include<iostream>
using namespace std;
class employee//类employee的声明
{
char name[30];//类内数组
float age;
public:
void getdata(void);
void putdata(void);
};
void employee::getdata(void)//类成员函数getdata的定义
{
cout<<"Enter name:";
cin>>name;
cout<<"Enter age:";
cin>>age;
}
void employee::putdata(void)//类成员函数putdata的定义
{
cout<<"Name:"<<name<<endl;
cout<<"Age:"<<age<<endl;
}
const int size=3;//定义一个整形常量,用于表示数组大小
int main()
{
employee manager[size];//定义了大小为size的类manager对象数组
for(int i=0;i<size;i++)
{
cout<<"\nEnter details of manager"<<i+1<<endl;//输入每个类对象的内容
manager[i].getdata();
}
cout<<endl;
for(int i=0;i<size;i++)
{
cout<<"Manager"<<i+1<<endl;//显示每个类对象的内容
manager[i].putdata();
cout<<endl;
}
return 0;
}
程序7.对象参数,即将对象作为函数的参数
//两种方法:1.传值:对象的整个副本传递给函数;2.传引用:只传递对象的地址
#include<iostream>
using namespace std;
class time//类time的声明
{
int hours;
int minutes;
public:
void gettime(int h,int m)//类内定义gettime函数
{
hours=h;
minutes=m;
}
void puttime(void)//类内定义puttime函数
{
cout<<hours<<" hours and ";
cout<<minutes<<" minutes "<<endl;
}
void sum(time,time);//声明成员函数sum,其中函数的参数为类time的对象
};
void time::sum(time t1,time t2)//sum函数的定义,t1、t2都是对象
{
minutes=t1.minutes+t2.minutes;
hours=minutes/60;
minutes=minutes%60;
hours=hours+t1.hours+t2.hours;
}
int main()
{
time T1,T2,T3;
T1.gettime(2,45);
T2.gettime(3,30);
T3.sum(T1,T2);//对象T3调用sum函数,对象T1、T2作为参数
cout<<"T1=";
T1.puttime();
cout<<"T2=";
T2.puttime();
cout<<"T3=";
T3.puttime();
return 0;
}
因为传引用时只需拷贝对象的地址,而不用吧整个对象复制过去,所以传引用方法的效率更高。
//程序8.友元函数
//声明为友元函数可以对类的私有数据有完全的访问权限
#include<iostream>
using namespace std;
class sample//声明类sample
{
int a;
int b;
public:
void setvalue() //设置a、b的值
{
a=25;
b=40;
}
friend float mean(sample s);//声明一个友元函数,格式:关键词(friend)+返回类型+函数名(参数列表)
//一个函数可以在任意多个类中声明为友元。};
float mean(sample s)//友元函数定义时不用加关键词friend,也不用使用作用域操作符::
{
return float(s.a+s.b)/2.0;//通过对象变量和点操作符,访问类变量a和b
}
int main()
{
sample X;
X.setvalue();
cout<<"Mean value="<<mean(X)<<endl;//对象X按传值法传递给友元函数
return 0;
}
特别要注意的是,友元函数和常规函数一样,不使用对象进行调用;可以声明在类的公共或私有部分。
/程序9.两个类的一个友元函数
//通过友元函数来连接两个类
#include<iostream>
using namespace std;
class ABC;//前置声明
class XYZ
{
int x;
public:
void setvalue(int i)
{
x=i;
}
friend void max(XYZ,ABC);//在两个类中都要声明该友元函数
};
class ABC
{
int a;
public:
void setvalue(int i)
{
a=i;
}
friend void max(XYZ,ABC);//在两个类中都要声明该友元函数
};
void max(XYZ m,ABC n)//友元函数的定义,不用再加关键词friend或类名
{
if(m.x>n.a)
{
cout<<m.x;
}
else
{
cout<<n.a;
}
}
int main()
{
XYZ xyz;//创建类对象
xyz.setvalue(20);//调用类XYZ成员函数setvalue
ABC abc;
abc.setvalue(10);
max(xyz,abc);//调用友元函数
cout<<endl;
return 0;
}
上述程序体现了不同的两个类中定义同一个友元函数,以此来连接两个类。
/程序10.交换类的私有数据
#include<iostream>
using namespace std;
class v1;//类v1的前置声明
class v2//类v2的定义
{
int value1;//创建类成员变量
public:
void indata(int a )//类内声明、定义成员函数
{
value1=a;
}
void display(void)
{
cout<<value1<<endl;
}
friend void exchange(v1 &,v2 &);//友元函数的声明,关键词friend
};
class v1
{
int value2;
public:
void indata(int a)
{
value2=a;
}
void display(void)
{
cout<<value2<<endl;
}
friend void exchange(v1 &,v2 &);
};
void exchange(v1 &x,v2 &y)//友元函数的定义,不用加关键词friend,也不用使用类名和作用域解析符::
{
int temp=x.value2;
x.value2=y.value1;//这是一个传引用函数的友元函数
y.value1=temp;
}
int main()
{
v1 c1;//创建类对象
v2 c2;
c1.indata(100);//调用类成员函数
c2.indata(500);
cout<<"Values before exchange"<<endl;//提示输出的内容
c1.display();
c2.display();
exchange(c1,c2);//直接调用友元函数,实现私有数据的交换
cout<<"Values after exchange"<<endl;
c1.display();
c2.display();
return 0;
}
上述程序利用友元函数传引用参数,来改变类的私有数据值。
//程序11.返回对象
#include<iostream>
using namespace std;
class complex//类complex的声明与定义
{
float x;
float y;
public:
void input(float real,float imag)//类内定义成员函数input
{
x=real;
y=imag;
}
friend complex sum(complex,complex);//友元函数
void show(complex);
};
complex sum(complex c1,complex c2)//对象作为参数
{
complex c3;
c3.x=c1.x+c2.x;
c3.y=c1.y+c2.y;
return (c3);//返回对象c3
}
void complex::show(complex c)
{
cout<<c.x<<"+j"<<c.y<<endl;
}
int main()
{
complex a,b,c;
a.input(3.1,5.65);
b.input(2.75,1.2);
c=sum(a,b);
cout<<"a=";
a.show(a);
cout<<"b=";
b.show(b);
cout<<"c=";
c.show(c);
return 0;
}
上述程序说明了函数不仅可以接受对象参数,也可以返回对象。
程序12.取值符,当使用对象和成员的指针时,用取值符->*来访问成员;当在对象中使用了成员指针时,则用取值符.*
//可以使用&操作符来获取成员的地址,
//声明一个类成员指针时,可以使用类名和操作符::*
#include<iostream>
using namespace std;
class M
{
int x;
int y;
public:
void set_xy(int a,int b)
{
x=a;
y=b;
}
friend int sum(M m);
};
int sum(M m)
{
int M::* px=&M::x;//指针px被创建后,必须使用类对象才能调用,&M::x表示:类M的成员x的地址
int M::* py=&M::y;//M::*表示:指向类M的成员的指针,&M::y表示:类M的成员y的地址
M *pm=&m;//pm为对象m的指针
int S=m.*px+pm->*py;//m.*px等价于m.x;pm->*py等价于pm->y
return S;
}
int main()
{
M n;
void (M:: *pf)(int,int)=&M::set_xy;//成员函数指针
(n.*pf)(10,20);//成员指针pf
cout<<"SUM="<<sum(n)<<endl;
M *op=&n;//对象指针op
(op->*pf)(30,40);
cout<<"SUM="<<sum(n)<<"\n";
return 0;
}
成员指针这是比较重要的,要区分好类成员指针(如,M::* py&M::y)与对象指针(如,n=&n)