静态与友元
8.1 圆类设计与应用
一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。圆周率以3.14参加计算。
#include <iostream>
#include <math.h>
using namespace std;
void showme(float r)//栏杆
{
cout<<"栅栏造价是"<<2*3.14*35*(r+3)<<"元"<<endl;
cout<<"过道造价是"<<3.14*(6*r+9)*20<<"元"<<endl;
}
int main()
{
float r;
cin>>r;
showme(r);
return 0;
}
8.2 西瓜类设计-静态数据成员的应用
王婆卖瓜过程:每卖一个瓜要记录该瓜重量,还要记录所卖出的瓜的总重量和所卖出瓜的总个数,同时还允许退瓜。要求采用面向对象的方法进行程序设计。
设西瓜类有4个数据成员:编号、重量、总重量(静态的数据成员)以及总个数(静态的数据成员)。
西瓜类的成员函数有4个:构造函数表示卖瓜、析构函数表示退瓜、显示卖出个数和总重量。
从键盘输入卖出几个瓜,每个瓜的编号和重量,以及要退第几个瓜。注意测试用例的输入输出。
#include<iostream>
using namespace std;
class Watermelon
{
private:
int no;
int weight;
static int total_weight;//静态成员表示总重量
static int total_number;//静态成员表示总个数
public:
static int GetTotal_number()
{
return total_number;
}
static int GetTotal_weight()
{
return total_weight;
}
Watermelon(int a=0,int b=0)
{
no=a;
weight=b;
total_weight+=weight;
total_number++;
}
~Watermelon()
{
total_number--;
total_weight-=weight;
}
};
int Watermelon::total_number=0;
int Watermelon::total_weight=0;
int main()
{
int t,i,n,w,k;
Watermelon *p[10];//定义对象指针数组,假设不超过10个,当然如果更多,可以定义大一点
cin>>t;//输入卖瓜的个数
for(i=0;i<t;i++)//卖瓜过程
{
cin>>n>>w;//输入卖出瓜的编号和重量
p[i]=new Watermelon(n,w);//动态申请内存
}
cout<<"卖出瓜总个数="<<p[0]->GetTotal_number()<<endl;
cout<<"卖出瓜总重量="<<p[0]->GetTotal_weight()<<endl;
cin>>k;//输入要退第几个瓜
delete p[k-1];//退第k个瓜,注意下标从0开始
cout<<"卖出瓜总个数="<<p[0]->GetTotal_number()<<endl;
cout<<"卖出瓜总重量="<<p[0]->GetTotal_weight()<<endl;
for(i=0;i<t;i++)//动态释放
{
if(i!=k-1)//注意k-1的下标,退瓜时已经被释放。
delete p[i];
}
return 0;
}
8.3 个人账户类设计-静态数据成员与静态成员函数的使用
设个人账户类有4个数据成员:账号、账户所有者、帐户余额以及利率(初值为0.03),要求从键盘输入卡号、用户名、所存钱数(对应余额),然后输出用户的余额和利率。为了验证该类,需要相应的成员函数以对这些数据成员进行操作。
#include <iostream>
#include <string>
using namespace std;
class Account
{
private:
string accountNumber;//账号
string owner;//所有者
double amount;//余额
static double interestRate;//静态成员表示利率
public:
static double GetRate()
{
return interestRate;
}
double GetAmout()
{
return amount;
}
Account(string a,string b,double c)
{
accountNumber=a;
owner=b;
amount=c;
}
};
double Account::interestRate=0.03;
int main()
{
string number,name;//定义字符串string 对象
double amount;
cin>>number>>name>>amount;//输入账号、用户名、用户余额
Account accou1(number,name,amount);//定义对象accou1
cout<<accou1.GetAmout()<<endl<<accou1.GetRate()<<endl; //输出余额和利率
cin>>number>>name>>amount;//输入账号、用户名、用户余额
Account accou2(number,name,amount);//定义对象accou2
cout<<accou2.GetAmout()<<endl<<accou2.GetRate()<<endl; //输出余额和利率
return 0;
}
8.4 学生类设计-静态数据成员和静态成员函数
设学生类包含一个静态数据成员,即学生个数。要求3个对象的姓名从键盘输入。注意:此题数据成员姓名要用使用string类对象。
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
string name;//姓名
static int number;//静态成员表示个数
public:
void Set(string &str)//注意参数是对象引用或者对象的区别
{
name=str;//string对象的赋值,注意此处=运算符重载
number++;//静态数据成员+1
}
static void PrintNumber()
{
cout<<number<<" total numbers"<<endl;//静态成员输出
}
void Print()
{
cout<<name<<"->students are "<<number<<" numbers"<<endl;
}
};
int Student::number=0;
int main()
{
string a,b,c;
cin>>a>>b>>c;
Student stu1,stu2,stu3;
stu1.Set(a);
stu1.Print();
stu1.PrintNumber();
stu2.Set(b);
stu2.Print();
stu2.PrintNumber();
stu3.Set(c);
stu3.Print();
stu3.PrintNumber();
return 0;
}
8.5 点类的应用-通过友元函数计算两点之间距离
设计一个点类,并为这个点类设置一个友元函数(friend double Distance1(Point &a, Point &b);)和一个普通函数(double Distance2( Point& a, Point& b);),分别用于计算两点间的距离。 注意:友元函数虽然在类中进行函数声明,但是不是类的成员函数。
#include <iostream>
#include <cmath>
using namespace std;
class Point //Point类声明
{public: //外部接口
Point(double xx=0.0, double yy=0.0)//带默认参数构造函数
{X=xx;Y=yy;}
double GetX( ) {return X;}
double GetY( ) {return Y;}
friend double Distance1(Point &a, Point &b); //友元函数声明
private: //私有数据成员
double X,Y;
};
double Distance1(Point &a, Point &b)
{
return sqrt((a.X-b.X)*(a.X-b.X)+(a.Y-b.Y)*(a.Y-b.Y));
}
double Distance2(Point &a, Point &b)
{
return sqrt((a.GetX()-b.GetX())*(a.GetX()-b.GetX())+(a.GetY()-b.GetY())*(a.GetY()-b.GetY()));
}
int main( )
{
Point p1(3.0, 5.0), p2(4.0, 6.0);
double d1=Distance1(p1, p2);//友元函数被调用
double d2=Distance2(p1, p2);//普通函数被调用
cout<<"The distance is "<<d1<<endl;//虽然d1和d2值一样但是访问私有数据的机制不同
cout<<"The distance is "<<d2<<endl;
return 0;
}
8.6 日期类和时间类1-友元成员函数用法
时间类的成员函数Display需要用到日期类的私有数据成员输出日期,方法1是将时间类的成员函数Display声明为日期类的友元函数。
#include <iostream>
using namespace std;
class Date;//类的前向引用声明,如果需要在某个类的声明之前,引用该类,则应进行前向引用声明。
class Time{ //时间类定义
private:
int hour, minute,second;
public:
void Display(Date &d);//在日期类中进行的友元函数声明,该函数是时间类成员函数,是日期类的友元函数
Time(int h=0,int m=0,int s=0) //带默认参数值的构造函数
{
hour=h;
minute=m;
second=s;
}
};
class Date{ //日期类定义
private:
int year, month,day;
public:
friend void Time::Display(Date &d);//在日期类中进行的时间类成员函数的友元函数声明,注意与普通友元函数不同,这里多了类名::
Date(int m=0,int d=0,int y=0) //带默认参数值的构造函数
{
month=m;
day=d;
year=y;
}
};
void Time::Display(Date &d)
{
cout<<d.month<<"/"<<d.day<<"/"<<d.year<<endl;
cout<<hour<<":"<<minute<<":"<<second<<endl;
}
int main( )
{
Date a(2012,12,25);
Time b(10,13,56);
b.Display(a);
return 0;
}
8.7 日期类和时间类2-友元类用法
时间类的成员函数Display需要用到日期类的私有数据成员输出日期,方法2是在日期类中将时间类声明为友元类(注意:为了与5.6题友元成员函数比较,此处的友元类声明与书上例2-39正好相反,那么main函数中使用需要注意这个变化),这样时间类的成员函数都是日期类的友元函数,当然包括时间类的Display函数也是日期类的友元函数了。
#include <iostream>
using namespace std;
class Date;//类的前向引用声明,如果需要在某个类的声明之前,引用该类,则应进行前向引用声明。
class Time{ //时间类定义
private:
int hour, minute,second;
public:
void Display(Date &d);//成员函数,由于Time是Date的友元类,所以Display函数是Date类的友元函数。
Time(int h=0,int m=0,int s=0) //带默认参数值的构造函数
{
hour=h;
minute=m;
second=s;
}
};
class Date{ //日期类定义
private:
int year, month,day;
public:
friend class Time;//定义Time类是Date类的友元类,则Time类的成员函数都是Date类的友元函数,当然时间类的Display函数也是日期类的友元函数了
Date(int m=0,int d=0,int y=0) //带默认参数值的构造函数
{
month=m;
day=d;
year=y;
}
};
void Time::Display(Date &d)
{
cout<<d.month<<"/"<<d.day<<"/"<<d.year<<endl;
cout<<hour<<":"<<minute<<":"<<second<<endl;
}
int main( )
{
Date a(2012,12,25);
Time b(10,13,56);
b.Display(a);
return 0;
}