C++类和对象数组
【1】对象数组
1:对象数组的定义:类名 数组名[元素个数]
Eg: student asa[10];//有10个元素的学生类对象数组
2:对象数组的访问形式:数组名[下标].成员名;
Eg: asa[j].print();
3:对象数组的初始化:对象数组的初始化通常也是由构造函数来完成的。
Eg: #include”student.h”
int main
{
student asa[4]={student(1,“LiMing”,98),student(2,”Bill”,89),student(3,”Chlily”,99),student(4,”Saraea”,96)};
for(int i=0;i<4;i++)
asa[i].print();
return 0;
}
【2】指向对象的指针
1:对象指针的用法:定义对象指针的语法和定义其它基本数据类型指针的语法相同。在使用对象指针之前,要把它指向一个已经创建的对象,然后才能访问该对象的成员。在使用对象名来访问对象成员时,要使用点运算符“.”。如果要通过指向对象的指针来访问对象的成员,那么必须使用箭头运算符“->”。
【3】this指针
Eg: class student
{
int number;
char name[15];
float score;
void display()
{
cout<<”number: ”<<number;
cout<<”name: ”<<name;
cout<<”score: ”<<score;<<endl;
}
};
1:在成员函数display()中有一个隐藏的指针作为参数,该指针参数使用关键字this命名,它是指向该类对象的指针,成员函数可以通过它来访问该类对象的数据成员。voiddisplay(student *this)//this指针由编译器自动生成。
2:this指针是由C++编译器自动产生的一个隐含指针,编译器将该指针自动插入到类的所有成员函数的参数列表中,成员函数使用该指针来存取对象的数据成员。
3:内存中只有一份成员函数的备份,而且对象的实例变量和成员函数是分开存放的,eg:X const *this。当对象调用该函数时,编译器自动将该对象的地址作为实参传递给相应的成员函数的this指针。
Eg:void date::set(date* constthis,int d,int m,int y)
{
this->day=d;
this->month=m;
this->year=y;
}
注意:this指针由编译器自动生成,程序员不能将this指针的说明写在函数中,否则将出现编译时间错误信息。
4:this指针是系统的一个内部指针,通常以隐式方式使用,但也可以被程序员显式使用,例如,当运算符重载和建立双向链表时,显式使用this指针十分必要。
【4】对象的赋值:如果两个对象属于同一种类类型,换句话说,两个对象是由同一个类声明的,那么我们可以将其中的一个对象的值(属性值)赋给另一个对象。默认情况下,当将一个对象赋值给另一个对象时,第一个对象的数据将被按位复制到第二个对象中。对象的赋值仅仅是使两个对象的值相等,而这两个对象仍然是相互独立的,即修改一个对象的值将不会影响到另一个对象。
Eg:Rectangle rect1(10,20),rect2(0,0);
rect2=rect1;
【5】对象作为函数参数:分类:传值调用,传址调用
1:传值调用:传值调用,传送的是作为实际参数的对象的拷贝而不是实际对象的本身。因此在函数中改变对象的值不会影响作为实际参数对象本身。
Class Square
{
int side;
public:
void set(int x) {side=x;}
void out() {cout<<side<<”\n”;}
};
void f(square x)
{
x.out();
x.set(100);
x.out();
}
int main()
{
Square s;
s.set(10);
f(s);
s.out();
return 0;
}
2:传址调用:当函数调用时传递的是作为实际参数的对象的地址,就是传址调用方式。在函数中对作为形式参数的对象的修改实际上就是对作为实际参数的对象的修改。我们既可以使用对象的引用来实现传址调用,也可以用指针来实现。
使用对象的引用来实现传址调用:
Class Square
{
int side;
public:
void set(int x){side=x;}
void out() {cout<<side<<”\n”;}
};
void f(square &x)//对象的引用作为函数的参数
{
x.out();
x.set(100);
x.out();
}
int main()
{
Square s;
s.set(10);
f(s);
s.out();
return 0;
}
使用指向对象的指针来实现传址调用的例子
Class Square
{
int side;
public:
void set(int x){side=x;}
void out() {cout<<side<<”\n”;}
};
void f(square *x)
{
x.out();
x.set(100);
x.out();
}
int main()
{
Square s;
s.set(10);
f(&s);
s.out();
return 0;
}
【6】从函数返回对象:当函数返回对象时,函数创建了一个临时对象来保存要返回的值,而函数所返回的对象实际上是这个临时对象。在对象的值被返回之后,临时对象将被销毁。
Eg:mystring input()
{
char instr[80];
mystring str;
cin>>instr;
str.set(instr);
return str;//返回一个mystring对象
}
int main()
{
Mystring ob;
ob=.input();
ob.print();
return 0;
}
【7】类的静态成员
1:静态成员:C中通过在变量定义的前面加static关键字就可以将变量声明为静态变量。采用局部静态变量可以减少全局变量的使用:将全局变量声明为静态的可以降低全局变量的副作用。C++中通过在类的成员函数前面加上static关键字将其成员声明为静态成员,一个类的静态成员既可以是静态数据成员,也可以是静态成员函数。
-
静态数据成员
声明类的静态数据成员的方式是在变量定义的前面加static关键字
classstudent
{
private:
int num;
char *name;
float score;
static int count;
static float sum;//类student的静态数据成员的声明
public:
……
};
intstudent::count=0;
floatstudent::sum=0; //静态成员变量应在创建类的对象前定义并进行初始化
一个类的静态数据成员为该类的所有对象所共有,不管创造了这个类的多少个对象,其静态数据成员在内存中只有一份拷贝。由于只有一个类的静态成员只有一份拷贝,所以我们经常使用“类名::”来访问静态数据成员。例如:counter::count=0;
静态成员变量的最一般的作用就是对一些共享资源提供存取控制。
静态成员好处就是减少了全局变量的使用。
静态成员主要作用就是定义类的各个对象所共用的数据,如统计总数,平均数等。
2:静态成员函数:在类的成员函数前面加上static关键字说明的函数就是静态成员函数。只使用静态数据成员的函数可以定义为静态成员函数。对静态成员函数的引用使用所属的类名加作用域分辨运算符来限制,即“类名::”。
Eg: classStudent
{
private:
……
public:
static void init()
{
Student::count=0;
Student::sum=0;
}
Static float average();
};
float student::average()
{
cout<<”sum is ”<<sum<<“\tcount is ”<<count<<endl;
cout<<”average is”<<sum/count<<endl;
return sum/count;
}
静态成员函数可以在创建该类的任何成员之前处理静态数据成员,这是普通成员函数不能实现的。一般来说,类的静态成员函数是用来访问静态数据成员的,当然可以访问全局变量。静态成员函数不具有this指针。也就是说,静态成员函数不与某个具体的对象相联系,它只属于该类。
【8】类的友元
1:友元函数:将关键字friend放在函数名的前面就将该函数说明为友元函数。一个类的友元函数是在该类中说明的一个非成员函数,但允许访问该类对象的所有成员。友元函数可以访问类的私有成员,节省了调用成员函数的开销,从而提高了程序的运行效率。如果需要一个函数同时访问多个类,则它可以定义为多个类的友元函数。1)使用友元破坏了封装性,降低了程序的可维护性。因此使用友元时要慎重的权衡得失后再决定。2)因为友元函数不是类的成员,故在友元函数中没有this指针,因此必须通过函数参数来传递对象。
2:友元类:若一个类为另一个类的友元,则次类的所有成员函数都能访问对方类的私有成员。下例所示:类B的所有成员函数都是类A的友元函数,都能够访问类A的所有成员。但是类A不是类B的友元类
Eg:class A
{
……
public:
friend class B;
……
};