类成员一般都需要通过对象来访问,不可以通过类名直接访问,但是当我们将类成员定义为静态类成员,则允许使用类名直接访问。
静态类成员是在类成员前定义static关键字。
1 #include<iostream>
2 using namespace std;
3 class Cbook
4 {
5 public:
6 static int price;
7 };
8 int Cbook::price = 410;
9 int main()
10 {
11 Cbook cbook;
12 cout<<"Cbook in"<<Cbook::price<<endl; //通过类名直接访问类成员
13 cout<<"Cbook use"<<cbook.price<<endl;//通过对象访问静态类成员
14
15
16 return 0;
17 }
注意:在定义静态类成员时,通常需要在类体外部对静态类成员进行初始化。
静态类成员是被所有的类共享的,无论定义多少个类对象。类的静态类成员只有一份,同时,如果一个对象修改了静态类成员,那么其他对象的静态类成员也将改变(修改的是同一个静态类成员)
静态类成员可以是当前类的类型,其他数据类成员只能是当前类的指针或应用类型,在定义类成员时,对于静态类成员,其类型可以是当前类的类型,而非静态类·成员则不可以,除非数据成员的类型为当前类的指针或引用类型。
8 class CBOOK
9 {
10 public:
11 static int price;
12 // CBOOK cbook;错误,非法定义
13 static CBOOK cook;
14 CBOOK *cbook;
15 };
静态类成员可以作为成员函数的默认参数,在定义类的成员函数时,可以为成员函数指定默认参数,其参数的默认值也可以是类的静态类成员,但是不同的数据成员不能作为成员函数的默认参数。
类的静态成员函数只能访问类的静态成员,而不能访问普通的数据成员。
而且静态类成员函数不能定义为const成员函数,如果函数的实现代码位于类体之外,则在函数的实现部分不能再标识static关键字。
友元概述
友元是使用friend关键字, 让特定的函数或者别的类的所有成员函数对私有数据成员进行读写。
好处是:可以保持数据的私有性,又可以让特定的类或者函数直接访问私有成员。
为了提升效率,友元可以让普通函数直接访问一个类的保护或私有数据成员,但是如果没有友元机制,就只能将类的数据成员声明为公共的,从而任何函数都可以无约束地访问它。
友元函数:
1 #include<iostream>
2 using namespace std;
3 class Friendfunction
4 {
5 public:
6 Friendfunction()
7 {
8 m_height = 0;
9 m_width = 0;
10 }
11 Friendfunction(int height,int width)
12 {
13 m_width = width;
14 m_height = height;
15 }
16 int getHeight()
17 {
18 return m_height;
19 }
20 int getWidth()
21 {
22 return m_width;
23 }
24 friend int friendfunction(Friendfunction &myret);
25 protected:
26 int m_height;
27 int m_width;
28 };
29 int friendfunction(Friendfunction &myret)
30 {
31 return myret.m_height*myret.m_width;
32 }
33 int main()
34 {
35 Friendfunction ff(120,210);
36 cout<<"result = "<<friendfunction(ff)<<endl;
37
38 return 0;
39 }
在函数friendfunction中可以直接使用Friendfunction类对象中的数据成员,就是因为第24行代码的作用:
24 friend int friendfunction(Friendfunction &myret);
此例子既很好的保护隐藏了数据,又可以使外界的特定函数直接访问这些隐藏数据。
接下来介绍友元类:
就如下面第14行代码所示 : friend class Clist; 就可以声明友元类啦。用法和功能与友元函数用法功能类似。这里就不再详细赘述了,直接看代码:
1 #include<iostream>
2 #include<string>
3 using namespace std;
4 class Cltem
5 {
6 private:
7 string m_name;
8 void outputname()
9 {
10 cout<<"name = "<<m_name<<endl;
11
12 }
13 public:
14 friend class Clist;
15 void setltemname(string name)
16 {
17 m_name= name;
18 }
19 };
20 class Clist
21 {
22 private:
23 Cltem m_ltem;
24 public:
25 void outoutltem();
26 };
27 void Clist::outoutltem()
28 {
29 m_ltem.setltemname("beijing");
30 m_ltem.outputname();
31 }
32 int main()
33 {
34 Clist list;
35 list.outoutltem();
36
37 return 0;
38 }
定义Cltem类时,使用了friend关键字将Clist类定义为Cltem类 的友元,这样一来,Clist类中的所有方法都可以访问Cltem类中的私有成员了。
在我们真正开发程序时,有时候需要控制一个类对当前类的私有成员的发法。比如,我们需要实现只允许Cbook类中的某个成员来访问·Clibrary类的私有成员,而不允许其他成员函数访问Clibrary类的私有数据,这可以通过定义友元函数来实现。在定义Clibrary类的时候,可以将Cbook类的某个方法定义为友元方法,这样就限制了只有该方法允许访问Clibrary类的私有成员。
1 #include<iostream>
2 using namespace std;
3 class Clibrary;
4 class Cbook
5 {
6 public:
7 Cbook();
8 ~Cbook();
9 Clibrary *position;
10 void putcbook(); //声明友元
11 //void notfriendcbook();//不声明友元,作为对比
12 };
13 class Clibrary
14 {
15 friend void Cbook::putcbook();
16 private:
17 string name;
18 void putname()
19 {
20 cout<<"name = "<<name<<endl;
21 }
22 public:
23 void setname(string name);
24 };
25 void Clibrary::setname(string name)
26 {
27 this->name = name;
28 }
29 void Cbook::putcbook()
30 {
31 position->setname("beijing");
32 position->putname();
33 } /*
34 void Cbook::notfriendcbook()
35 {
36 position->setname("beijing");
37 position->putname();
38 }*/
39 Cbook::Cbook()
40 {
41 position = new Clibrary();
42 }
43 Cbook::~Cbook()
44 {
45 delete position;
46 position = NULL;
47 }
48
49 int main()
50 {
51 Cbook cook;
52 cook.putcbook();
53
54 // cook.notfriendcbook();
55 return 0;
56 }
就像上面代码所示,如果把没有声明友元的成员函数放开,就会出现下面这样的错误。
[bsk@localhost c++]$ g++ friendmethod.cpp
friendmethod.cpp: In member function ‘void Cbook::notfriendcbook()’:
friendmethod.cpp:18:10: error: ‘void Clibrary::putname()’ is private
void putname()
^
friendmethod.cpp:37:23: error: within this context
position->putname();
原因也很简单,就是因为notfriendcbook()成员函数不是Clibrary类的友元,所以这个成员函数就不能访问去访问Clibrary类中的私有属性。
此外,全局函数也可以作为类友元,一样可以访问类中的私有成员。
最后简单来谈一下
友元函数在访问类对象中的成员时,不需要通过对象名。友元函数没有this指针,如果不通过对象名就无法找到类对象中的非static成员,也就无法访问。但是当访问类对象中的static成员时,就可以不用通过对象名访问。