目录
3.10 友元
3.10.1友元函数
3.10.2 友元类
3.11 类模板
3.10 友元
3.10.1友元函数
如果在本类以外的其他地方定义了一个函数(这个函数可以说是不属于任何类的非成员函数,也可以是其他类的成员函数),在类体中用friend对其进行声明,此函数就称为本类的友元函数。
1.将普通函数声明为友元函数
#include
using namespace std;
class Time
{
public:
Time(int, int, int);
friend void display(Time&);//声明display函数是为Time类的友元函数
private:
int hour;
int minute;
int sec;
};
Time::Time(int h, int m, int s)
{
hour = h;
minute = m;
sec = s;
}
void display(Time &t)
{
cout << t.hour << ":" << t.minute << ":" << t.sec << endl;//必须加上对象名
//因为display函数不是Time类的成员函数,没有this指针,不能默认引用Time类的数据成员,必须指定要访问的对象
}
int main()
{
Time t1(12, 13, 14);
display(t1);
return 0;
}
2.友元成员函数
friend函数不仅可以是一般函数(非成员函数),而且可以是另一个类中的成员函数。
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
class Date;//声明Date类!!!“提前引用”
class Time
{
public:
Time(int, int, int);
void display(Date&);//声明display函数是为Time类的友元函数
private:
int hour;
int minute;
int sec;
};
class Date
{
public:
Date(int, int, int);
friend void Time::display(Date&);//允许display函数使用私有成员数据
private:
int month;
int day;
int year;
};
Time::Time(int h, int m, int s)
{
hour = h;
minute = m;
sec = s;
}
void Time::display(Date& d)
{
cout << d.month << "/" << d.day << "/" << d.year << endl;
cout << hour << ":" << minute << ":" << sec << endl;
}
Date::Date(int m, int d, int y)
{
month = m;
day = d;
year = y;
}
int main()
{
Time t1(10, 13, 56);
Date d1(12, 25, 2004);
t1.display(d1);
return 0;
}
类的提前声明的适用范围是有限的,只有在正式声明一个类以后才能用它去定义对象。
一个函数可以被多个类声明为“朋友”,这样就可以引用多个类中的私有数据。
3.10.2 友元类可以将一个类B声明为另一个类A的“朋友”,此时B就是A的友元类。
声明友元类的一般形式:
friend 类名;
如上例中:
说明:
(1)友元的关系是单向的而不是双向的。
(2)友元的关系不能传递。
关于友元利弊分析:面向对象程序设计的一个基本原则是封装性和信息隐蔽,而友元却可以访问其他类中的私有成员,不能不说这是对封装原则的一个小的破坏。但是它能有助于数据共享,能提高程序的效率,在使用友元时,要注意到它的副作用,不要过多地使用友元,只有在使用它能使程序精练,较大地提高程序效率时才用友元。也就是说,要在数据共享与信息隐蔽之间选择一个恰当的平衡点。
3.11 类模板用一个模板实现一类多用
template
由于类模板包含类型参数,因此又称为参数化的类。
类模板是类的抽象,类是类模板的实例。
一般形式为:
类模板名 <实际类型名>对象名(参数表);
Compare
cmp(4,7);
#include
using namespace std;
template
class Compare
{
public:
Compare(numtype a, numtype b)
{
x = a; y = b;
}
numtype max()
{
return (x > y )? x : y;
}
numtype min()
{
return (x < y) ? x : y;
}
private:
numtype x;
numtype y;
};
int main()
{
Comparecmp1(3, 7);
cout << cmp1.max() << "是最大值。" << endl;
cout << cmp1.min() << "是最小值。" << endl;
Comparecmp2(3.6, 7.9);
cout << cmp2.max() << "是最大值。" << endl;
cout << cmp2.min() << "是最小值。" << endl;
Compare cmp3('a', 'A');
cout << cmp3.max() << "是最大值。" << endl;
cout << cmp3.min() << "是最小值。" << endl;
}
在类模板外点过成员函数时,不能用一般定义类成员函数的形式。
应当写成类模板的形式:
template
template Conpare
::max() {return (x>y)?x:y;}
归纳
1)先写出一个实际的类(如本节开头的 Compare_int )。由于其语义明确,含义清楚,一般不会出错。
(2)将此类中准备改变的类型名(如 int 要改变为 float 或 char )改用一个自己指定的虚拟类型名(如上例中的 numtype )。
(3)在类声明前面加入一行,格式为
template < class 虚拟类型参数>//注意本行末尾无分号
template < class numtype >class Compare
{...};//类体
(4)用类模板定义对象时用以下形式:
类模板名<实际类型名>对象名;
类模板名<实际类型名>对象名(实参表);
compare < int > cmp ;
compare < int > cmp (3,7);
(5)如果在类模板外定义成员函数,应写成类模板形式:
template < class 虚拟类型参数>
函数类型 类模板名<虚拟类型参数>::成员函数名(函数形参表){…}
说明:
(1)类模板的类型参数可以有一个或多个,毎个类型前面都必须加 class
template < class T1, class T2>
class someclass
{…};
(2)和使用类一样,使用类模板时要注意其作用域(在同一个文件中使用)
(3)模板可以有层次,一个类模板可以作为基类,派生出派生模板类。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)