对象数组
将一系列的对象存放到一个数组里
建立对象数组的时候,有几个数组成员就要调用几次构造函数
#对只有一个数据成员的类,可以用只有一个参数的构造参数或者不带参数的构造函数来赋值
class exam{
private:
int x;
public:
exam(){x=123;}
exam(int n){x=n;}
};
exam ob1[4]={11,22,33,44};
exam ob3[4]={55,66}//剩两个默认123
#构造函数有多个参数时
score rec[3]={
score(80,88),
score(90,92),
score(70,80)
};
对象指针
类似于结构体指针,访问时将“ . ”换成 “ -> ”
string类
字符串的类,更方便好用(具体用法以前都学过了)
#两种初始化方式
string str("china");
string str="china";
用函数传递对象
对象直接作为参数<传值>
对象指针作为参数<传址>
对象引用作为参数<传址>
静态成员 static
静态成员的声明直接在原来形式的基础上加上 static
静态数据成员
无论建立多少个对象,只有一个静态数据成员的拷贝,因此静态数据成员是同一类的成员之间共享的
静态数据成员初始化应该在类外单独进行,而且要在定义对象之前进行(main函数之前,类声明之后的地方)
数据类型 类名::静态数据成员名=初始值
int score::count=0;
静态数据成员属于类中对象的集合(属于类)可以直接使用 类名::访问静态数据成员
cout<<score::count;
静态数据成员在编译时创建并初始化,在该类的对象建立之前就存在,可以在对象定义之前就访问;公有的静态数据成员可以通过对象进行访问,私有的静态数据成员只能被公有的成员函数访问
静态成员函数
一般而言,静态成员函数不访问类中的非静态成员,只能通过对象名、对象指针、对象引用来访问,因为静态成员函数没有this指针
编译系统将静态成员函数限定为内部连接
举个栗子:
#include<iostream>
using namespace std;
class Score{
private:
int mid;
int fin;
static int count;//声明
static float sum;
static float ave;
public:
Score(int m,int f);
static void display(Score & s){
cout<<"期末成绩:"<<s.fin<<endl;
}
static void show(){
cout<<"学生人数:"<<count<<endl;
cout<<"总成绩:"<<sum<<endl;
cout<<"期末平均成绩:"<<ave<<endl;
}
};
Score::Score(int m,int f){
mid=m;
fin=f;
count++;
sum+=fin;
ave=sum/count;
}
//初始化
int Score::count=0;
float Score::sum=0.0;
float Score::ave=0.0;
int main()
{
Score rec[3]={
Score(80,88),
Score(90,92),
Score(70,80),
};
Score::display(rec[0]);
Score::display(rec[1]);
Score::display(rec[2]);
Score::show();
return 0;
}
友元 friend
友元是类的隐藏和封装这堵不透明的墙上的小孔,是一扇通往私有成员的后门;
友元函数
友元函数的声明,直接在函数声明之前关键词 friend
(1)友元函数可以是不属于任何类的非成员函数,也可以是另一个类的成员函数。友元函数不是当前类的成员函数,但是可以访问该类的所有的成员。
(2)友元函数不属于当前类,因此在当前类外定义友元函数的话,不需要在前面加上 类名::
(3)友元函数不能直接访问对象的成员,也不能通过this指针,只能通过入口参数传递的对象名、指针、引用来访问
(4)当一个函数需要访问多个类的时候,友元函数就是很好的选择
可以将一个类的成员函数作为另一个类的友元函数
友元类
当一个类被声明为另一个类的友元类时,他的所有成员函数都成为另一个类的友元函数,即友元类的所有成员都可以访问另一个类的所有成员
友元关系是单向的,不具有交换性和传递性,是否具有友元关系只能从是否有友元定义来确定
下面是一个关于友元的栗子
#include<iostream>
#include<string>
using namespace std;
class Score;//提前引用声明
class Student{
private:
string name;
int number;
public:
Student(string na,int num){
name=na;
number=num;
}
void show(Score &sc);//对象的传递
};
class Score{
private:
int mid_exam;
int fin_exam;
public:
Score(int m,int f){
mid_exam=m;
fin_exam=f;
}
friend void get(Score &sc);//将非成员函数声明为友元函数
friend void Student::show(Score &sc);
//将Student的成员函数声明为Score的友元函数
//将上面那一行换成
//friend Student;
//即可实现友元类的定义
};
void get(Score &sc){//声明不需要 类名::
cout<<"总评成绩 "<<(int)(0.3*sc.mid_exam+0.7*sc.fin_exam)<<endl;
}
void Student::show(Score &sc){
//成员函数可以直接访问数据成员
cout<<"姓名 "<<name<<endl<<"学号 "<<number<<endl;
//友元函数需要对象的传递才能访问
cout<<"期中成绩 "<<sc.mid_exam<<endl<<"期末成绩 "<<sc.fin_exam<<endl;
}
int main()
{
Score sco(90,92);
Student stu("jiajia",207084);
//两种友元函数的调用
stu.show(sco);
get(sco);
return 0;
}
类的组合
在一个类中嵌套另一个类的对象作为数据成员,成为类的组合 内嵌对象成为对象成员,又称子对象
创建对象时,内嵌对象将自动被创建,那么就需要对对象和对象成员进行初始化,构造函数因此升级
X::X(形参表0):对象成员名1(形参表1),......,对象成员名n(形参表n){类X的构造函数体}
(1)声明一个含有对象成员的类,首先要创建各成员对象
(2)使用构造函数进行初始化的时候,也要对对象成员初始化,并且是先调用对象成员的构造函数,再执行原类的构造函数
构造函数中 应该使用对象成员名,而不是它的类
举个栗子
//学生类中嵌套有个日期类的对象,并显示学生姓名和出生日期
#include<iostream>
#include<string>
using namespace std;
class Date{
private:
int year;
int month;
int day;
public:
Date(int y,int m,int d);
void showDate();
};
Date::Date(int y,int m,int d){
year=y;
month=m;
day=d;
}
void Date::showDate(){
cout<<year<<"."<<month<<"."<<day<<endl;
}
class Stu{
private:
string name;
Date birthday;//声明成员对象(子对象)
public:
//构造函数同时需要构造成员对象
Stu(string name1,int yy,int mm,int dd);
void show();
};
//注意构造函数的写法 先将子对象初始化 再执行构造函数体
Stu::Stu(string name1,int yy,int mm,int dd):birthday(yy,mm,dd){
name=name1;
}
void Stu::show(){
cout<<"姓名:"<<name<<endl;
cout<<"出生日期:";
birthday.showDate();
}
int main()
{
Stu stu("yang",2000,9,19);
stu.show();
return 0;
}