类的静态成员
1.静态数据成员(static)
- 类的静态数据成员是由该类的所有对象共同维护和使用
- 类的声明是抽象的,因此类中只能声明静态数据成员,即静态数据成员的初始化需要在类的外部进行
- 类的声明是抽象的,可以通过类名直接访问静态数据成员,用法为“类名::标识符”
例:统计学生数目
class student
{
public:
student(const char *s);
~student();
private:
static int count; //无法直接初始化
string name;
};
int student::count=0;
Student::Student(const char *s)
{
name=s;
count++;
}
Student::~Student()
{
count--;
cout<<name<<" is dead "<<count<<endl;
}
int main(int argc, char** argv)
{
Student a("zhangsan");
Student b("lisi");
Student c("wangwu");
}
2.静态成员函数(static)
- 类的静态成员函数是由该类的所有对象共同维护和使用
上面代码Student类加一个静态成员函数
static void print()
{
cout<<count<<endl;
}
主函数添加
a.print();
类的组合
一个类内嵌其他类的对象作为数据成员的情况。
创建组合类的对象时,各个内嵌对象也将被自动创建。
内嵌类的构造函数:
类名::类名(形参表):内嵌对象1(形参表),内嵌对象2(形参表)…
{
}
构造函数调用顺序:按照组合类中声明顺序先执行内嵌对象构造函数,再执行自身构造函数
#include<bits/stdc++.h>
using namespace std;
class A1
{
public:
A1(int x,int y);
~A1();
private:
int value1;
int value2;
};
A1::A1(int x,int y)
{
value1=x;
value2=x;
cout<<"A1 is finished\n";
}
A1::~A1()
{
cout<<"A1 is dead\n";
}
class A4
{
public:
A4(int x,int y);
~A4();
private:
int value1;
int value2;
};
A4::A4(int x,int y)
{
value1=x;
value2=x;
cout<<"A4 is finished\n";
}
A4::~A4()
{
cout<<"A4 is dead\n";
}
class A
{
public:
A(int x,int y);
~A();
private:
A1 a; //a先声明
A4 b; //b后声明
};
A::A(int x,int y):a(x,y),b(y,x)
{
cout<<"A is finished\n";
}
A::~A()
{
cout<<"A is dead\n";
}
int main(int argc, char** argv)
{
A c(1,2);
}
内嵌对象声明顺序为a,b
构造函数执行顺序为a,b,A
析构函数执行顺序为A,b,a(其中内嵌对象所在类A1,A4析构函数必须手动声明)
友元(friend)
可以访问类的私有成员和保护成员的外部成员
关键字friend可以将(一般函数,其他类的成员函数,其他类)声明为本类的友元,这样友元可以访问本类的隐藏信息(private和protected)
1.友元函数
友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,他和普通函数相同,即在定义上和调用上和普通函数相同。下面举一例子说明友元函数的应用。
class Point
{
public:
Point(double xx, double yy)
{
x=xx; y=yy;
}
void Getxy();
friend double Distance(Point &a, Point &b); //该函数是友元函数的声明
private:
double x,y;
};
{
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx*dx+dy*dy);
}
void Point::Getxy()
{
cout<<"("<<x<<","<<y<<")"<<endl;
}
int main()
{
Point p1(3.0,4.0);
Point p2(6.0,8.0);
p1.Getxy();
p2.Getxy();
double d = Distance(p1, p2);
cout<<"Distance is "<<d<<endl;
}
2.友元类
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:
friend class 类名;
其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。
例如,以下语句说明类B是类A的友元类:
class A
{
…
public:
friend class B;
…
};
经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。
#include <iostream>
using namespace std;
class A
{
public:
friend class C; //这是友元类的声明
private:
int data;
};
class C //友元类定义,为了访问类A中的成员
{
public:
void set_show(int x, A &a) { a.data = x; cout<<a.data<<endl;}
};
int main(void)
{
class A a;
class C c;
c.set_show(1, a);
return 0;
}
3、友元成员函数
使类B中的成员函数成为类A的友元函数,这样类B的该成员函数就可以访问类A的所有成员了。
当用到友元成员函数时,需注意友元声明和友元定义之间的相互依赖,在该例子中,类B必须先定义,否则类A就不能将一个B的函数指定为友元。然而,只有在定义了类A之后,才能定义类B的该成员函数。更一般的讲,必须先定义包含成员函数的类,才能将成员函数设为友元。另一方面,不必预先声明类和非成员函数来将它们设为友元。
#include <iostream>
using namespace std;
class A; //当用到友元成员函数时,需注意友元声明与友元定义之间的互相依赖。这是类A的声明
class B
{
public:
void set_show(int x, A &a); //该函数是类A的友元函数
};
class A
{
public:
friend void B::set_show(int x, A &a); //该函数是友元成员函数的声明
private:
int data;
void show() { cout << data << endl; }
};
void B::set_show(int x, A &a) //只有在定义类A后才能定义该函数,毕竟,它被设为友元是为了访问类A的成员
{
a.data = x;
cout << a.data << endl;
}
int main(void)
{
class A a;
class B b;
b.set_show(1, a);
return 0;
}
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明