1.静态成员:静态数据成员在类外定义,在类内声名;
//静态数据成员
#include <iostream.h>
class Student{
public:
static int count; //声名为静态数据成员
int StudentNo;
public:
Student()
{ count++; //创建一个Student count 加加
StudentNo=count;
}
void print()
{ cout<<"Student "<<StudentNo<<" ";
cout<<"count="<<count<<endl;
}
};
int Student::count=0; //定义静态数据成员并初始化
void main()
{
Student s1;
s1.print();
cout<<"------/n";
Student s2;
s1.print();
s2.print();
cout<<"------/n";
//可以在外面操作变量
//Student::count=99 此时输出:1-22-100 100 100
Student s3;
s1.print();
s2.print();
s3.print();
cout<<"------/n";
}
结果:1-22-333
2.所以当使用全局变量的时候,可以使用静态成员,函数间是共享的。其实啊类是不能分配空间的,因为是个声明而已,初始化才赋值。
3.使用静态使得可以代替全局,这样就符合C++的封装性!一般用来定义一些共有的数据;如统计总数、平均数等。
// 使用静态成员函数访问静态数据成员
#include <iostream.h>
class small_cat{
private:
double weight;
static double total_weight; //静态数据成员
static double total_number; //静态数据成员
public:
small_cat(double w)
{ weight=w;
total_weight+=w;
total_number++;
}
void display()
{
cout<<"小猫的重量是:"<<weight<<"磅"<<endl;
}
//static void total_disp() //静态成员函数
void total_disp()
{
cout<<total_number<<"只小猫总重是:"<<total_weight<<"磅"<<endl;
}
};
double small_cat::total_weight=0;
double small_cat::total_number=0;
void main()
{ small_cat w1(1.88),w2(1.66),w3(1.55);
w1.display();
w2.display();
w3.display();
small_cat::total_disp(); //通过类调用静态成员函数
// w1.total_disp();
}
4.对静态成员的访问采用的是 类名::,对象.静态成员函数名()也对;
在声明时加static(类的里面用),使用时只需 类名::静态成员函数名();
5.一般而言,静态成员函数不能访问类中的非静态成员。(因为没有this指针,不知道该访问哪个对象的成员了)。
6. // 使用友元函数
#include <iostream.h>
#include <string.h>
class girl{
private:
char *name;
int age;
public:
girl(char *n,int d)
{ name=new char[strlen(n)+1];
strcpy(name,n);
age=d; //实际 this->age = d;隐藏了this指针。
}
friend void disp(girl &); //声明为友元函数,可以放在共有或私有的部分。不能值传递!
// friend void disp(girl x); 错误!涉及内存权限。虽然可以通过编译,指针可以
新建的对象x,e的所有均复制到x。 name age |
对象e name age |
new |
new |
~girl(){delete name;}
};
但是传值后x的name又指向e的new了,(复制的是地址),而x的new成为垃圾空间。
// void disp(girl x)
void disp(girl &x) //定义友元函数,不属于这个类,但在类中声明,注意参数!
{ //实际上是通过引用操作类的成员。
cout<<"girl/'s name is:"<<x.name<<",age:"<<x.age<<endl;
}
void main()
{ girl e("Chen Xingwei",18);
disp(e); //调用友元函数
}
友元函数不是当前类的成员函数,而是独立于当前类的外部函数,但它可以访问该类的所有对象的成员,包括私有成员和公有成员。不用 类名::函数名();
7. //使用一个友元函数访问两个不同的类
#include <iostream.h>
#include <string.h>
class boy; //向前引用,否则在下面的const boy会不认识的!
class girl{
char name[25];
int age;
public:
void init(char N[],int A);
friend void prdata(const girl &plg,const boy &plb); //声明函数为girl类的友元函数,引用
};
void girl::init(char N[],int A)
{ strcpy(name,N);
age=A;
}
class boy{
char name[25];
int age;
public:
void init(char N[],int A);
friend void prdata(const girl &plg,const boy &plb); //声明函数为boy类的友元函数
};
inline void boy::init(char N[],int A)
{ strcpy(name,N);
age=A;
}
//void prdata(const girl plg,const boy plb) //加const保护数据
void prdata(const girl &plg,const boy &plb) //如上所有改为引用也可,只不过起了外号而已,实际还是同一个对象。而上面的(不包括这个)const girl &plg,const boy &plb可以变为
(const girl &,const boy &)声明的问题。
{
cout<<"女孩"<<plg.name<<','<<plg.age<<"岁";
cout<<"男孩"<<plb.name<<','<<plb.age<<"岁。/n";
}
void main()
{ girl G1,G2,G3;
boy B1,B2,B3;
G1.init("Stacy",12);
G2.init("Judith",13);
G3.init("Leah",12);
B1.init("Jim",11);
B2.init("Micheal",13);
B3.init("Larry",12);
prdata(G1,B1);
prdata(G2,B2);
prdata(G3,B3);
}
一定要谨慎使用,防止对数据的错误操作。
8. // 使用友元成员函数访问另一个类
#include <iostream.h>
#include <string.h>
class girl; //向前引用(当出现两个及以上类时需要向前引用!)
class boy{
char *name;
int age;
public:
boy(char *N,int A)
{ name=new char[strlen(N)+1];
strcpy(name,N);
age=A;
}
void disp(girl &); //声明disp()为类boy的成员函数
~boy(){delete name;}
};
class girl{
char *name;
int age;
public:
girl(char *N,int A)
{ name=new char[strlen(N)+1];
strcpy(name,N);
age=A;
}
friend void boy::disp(girl &); //声明类boy的成员函数disp()为类girl的友元函数
~girl(){delete name;}
};
void boy::disp(girl &x)
{
cout<<"boy/'s name is:"<<name<<",age:"<<age<<endl; //访问本类对象成员
// cout<<"boy/'s name is:"<<this->name<<",age:"<<this->age<<endl;//类的成员函数,隐藏this
cout<<"girl/'s name is:"<<x.name<<",age:"<<x.age<<endl; //访问友元类对象成员必须指明对象x,因为没有this
}
void main()
{ boy b("chen hao",25);
girl g("zhang wei",18);
b.disp(g);
}
说明:
- 友元关系是单向的,不具有交换性(我是你的朋友,不能推断出:你是我的朋友)。
- 友元关系也不具有传递性(我是你的朋友,你是他的朋友,不能推断出:我是他的朋友)//概念记清,面试所需!
9. //对象作为类的数据成员
#include <iostream.h>
#include <string.h>
class string{
private:
char *str;
public:
string(char *s)
{ str=new char[strlen(s)+1];
strcpy(str,s);
cout<<"构造string/n";
}
void print(){cout<<str<<endl;}
~string()
{ cout<<"析构string/n";
delete str;
}
};
class girl{
private:
string name;
int age;
public:
girl(char *st,int ag):name(st) //注意格式 X::X(参数表0) : 成员名1(参数表1),……,成员名n(参数n表)
{ age=ag;
cout<<"构造girl/n";
}
void print()
{ name.print();
cout<<"age:"<<age<<endl;
}
~girl()
{ cout<<"析构girl/n";
}
};
void main()
{ girl obj("Chen hao",25);
obj.print();
}
从main函数开始—先新建girl对象obj,说明:
- 声明一个含有对象成员的类,首先要创建各成员对象。本例在声明类girl中,定义了对象成员:string name。
- girl类对象在调用构造函数进行初始化的同时,也要对对象成员进行初始化,因为它也是属于此类的成员。因此在写类girl的构造函数时,也缀上了对对象成员的初始化:
girl(char *st,int ag):name(st)
于是在调用girl的构造函数进行初始化时,也给对象成员name赋上了初值。
这里需要注意的是:在定义类girl的构造函数时,必须缀上其对象成员的名字name,而不能缀上类名,即:
girl(char *st,int ag):string(st)
是错误的,因为在类girl中是类string的对象name作为成员,而不是类string作为其成员。
(再次重申: 概念很要,面试所需!)