大家好,又见面了,我是你们的朋友全栈君。
C++对象数组
一、对象数组
1.C++对象数组的定义:类名 数组名[元素个数]
例:Student stu[10];
2.对象数组访问形式:数组名[下标].成员名;
例:stu[i].print();
3.对象数组的初始化:对象数组的初始化通常也是由构造函数来完成的
例:
关于对象数组的几点说明:
(1)在建立对象数组的时候需要调用构造函数。如果对象数组有100个元素,就需要调用100次构造函数。
(2)如果对象数组所属类有带参数的构造函数时,可用初始化列表按顺序调用构造函数,使用复制初始化来初始化每个数组元素。
Student A[3]={Student(1,liu,1),Student(2,li,2),Student(3,he,3)};
Student A[3]={Student(1),Student(2),Student(3)};
(3)如果对象数组所属类有单个参数的构造函数时,定义数组时可以直接在初值列表中提供实参。
例:只有一个参数的构造函数给对象数组赋值。
#include<iostream>
using namespace std;
class exam{
public:
exam(int n){ //只有1个参数的构造函数
x=n;
}
int get_x(){
return x;
}
private:
int x;
};
int main(){
exam ob1[4]={11,22,33,44}; //用只有1个参数的构造函数给对象数组赋值
for(int i=0;i<4;i++)
cout<<ob1[i].get_x()<<" ";
return 0;
}
当各个元素的初始值相同时,可以在类中定义不带参数的构造函数或者带有默认值的构造函数;当各个元素的的初始值要求不同时,需要定义带参数(无默认值)的构造函数。
例:用不到参数和带1个参数饿构造函数给对象数组进行赋值
#include <iostream>
using namespace std;
class Student{
public:
Student(){
score=100;
}
Student(int n){
score=n;
}
int get_score(){
return score;
}
private:
int score;
};
int main(){
Student stu[4]={60,70,80,90};
Student stu1[4]={60,70};
Student stu2[4];
for(int i=0;i<4;i++)
cout<<stu[i].get_score()<<" ";
cout<<endl;
for(int i=0;i<4;i++)
cout<<stu1[i].get_score()<<" ";
cout<<endl;
for(int i=0;i<4;i++)
cout<<stu2[i].get_score()<<" ";
cout<<endl;
return 0;
}
二、构造函数拥有多个参数
如果构造函数有多个参数,在定义对象数组时只需在花括号中分别写出构造函数并指定实参即可实现初始化。
例3:用带有两个参数的构造函数给对象进行赋值
#include<iostream>
#include <cmath>
using namespace std;
class Complex{
public:
Complex(double r=0.0,double i=0.0):real(r),imag(i){
}
~Complex(){
cout<<"Destructor caller"<<endl;
}
double absComplex(){
double t;
t=real*real+image*imag;
return sqrt(t);
}
private:
double real;
double imag;
};
int main(){
Complex com[3]={ //定义对象数组
Complex(1.1,2.2), //调用构造函数,为第一个对象数组元素提供实参1.1和2.2
Complex(3.3,4.4),
Complex(5.5,6.6)
};
cout<<"复数1绝对值为:"<<com[0].absComplex()<<endl;
cout<<"复数2绝对值为:"<<com[1].absComplex()<<endl;
cout<<"复数3绝对值为:"<<com[2].absComplex()<<endl;
return 0;
}
对象数组中的元素同样需要用构造函数初始化。具体哪些元素用哪些构造函数初始化,取决于定义数组时的写法。
#include <iostream>
using namespace std;
class CSample{
public:
CSample(){
cout<<"Constructor 1 Called"<<endl;
}
CSample(int n){
cout<<"Constructor 2 Called"<<endl;
}
};
int main(){
CSample array1[2];
cout<<"step1"<<endl;
CSample array2[2]={4,5};
cout<<"step2"<<endl;
CSample array3[2]={3};
cout<<"step3"<<endl;
CSample* array4=new CSample[2];
delete [] array4;
return 0;
}
array1 数组中的两个元素没有指明如何初始化,要用无参构造函数初始化,因此输出两行 Constructor 1 Called。
array2 数组进行了初始化,初始化列表 {4, 5} 可以看作用来初始化两个数组元素的参数,所以 array2[0] 以 4 为参数,调用构造函数 2 进行初始化;array2[1] 以 5 为参数,调用构造函数 2 进行初始化。这导致输出两行 Constructor 2 Called。
array3 只指出了 array3[0] 的初始化方式,没有指出 array3[1] 的初始化方式,因此它们分别用构造函数 2 和构造函数 1 进行初始化。
动态分配了一个 CSample 数组,其中有两个元素,没有指出和参数有关的信息,因此这两个元素都用无参构造函数初始化。
在构造函数有多个参数时,数组的初始化列表中要显式包含对构造函数的调用。
class Student{
public:
Student(int n){ } //构造函数(1)
Student(int n, int m){ } //构造函数(2)
Student(){ } //构造函数(3)
};
int main(){
//三个元素分别用构造函数(1)、(2)、(3) 初始化
Student arrayl [3] = { 1, Student(1, 2) };
//三个元素分别用构造函数(2)、(2)、(1)初始化
Student array2[3] = { Student(2,3), Student(1,2), 1};
//两个元素指向的对象分别用构造函数(1)、(2)初始化
Student* pArray[3] = { new Student(4) , new Student(1,2) };
return 0;
}
pArray 数组是一个指针数组,其元素不是Student 类的对象,而是Student类的指针。Student* pArray对 pArray[0] 和 pArray[1] 进行了初始化,把它们初始化为指向动态分配的Student对象的指针,而这两个动态分配出来的 Student对象又分别是用构造函数(1)和构造函数(2)初始化的。pArray[2] 没有初始化,其值是随机的,不知道指向哪里。Student* pArray生成了两个Student对象,而不是三个,所以也只调用了两次 Student类的构造函数。
从栈区和堆区两种存储方式上看它的使用
#include <iostream>
using namespace std;
class Coordinate
{
public:
Coordinate(){};//无参构造函数
~Coordinate(){};//析构函数
public:
int m_iX;
int m_iY;
};
int main()
{
Coordinate coor[3];
coor[0].m_iX=1;
coor[0].m_iY=2;
coor[1].m_iX=3;
coor[1].m_iY=4;
coor[2].m_iX=5;
coor[2].m_iY=6;//类似数组直接访问
Coordinate *p=new Coordinate[3];
p->m_iX=7;//默认访问首地址
p[0].m_iY=8;//与上面一行指向的都是首地址
p++;//指针往后指一个
p->m_iX=9;
p->m_iY=10;
p++;//指针往后指一个
p->m_iX=11;
p->m_iY=12;
p--;
p--;
for(int i=0;i<3;i++)
{
cout<<coor[i].m_iX<<" ";
cout<<coor[i].m_iY<<" ";
cout<<"\n";
}
for(int j=0;j<3;j++)
{
cout<<p[j].m_iX<<" ";
cout<<p[j].m_iY<<" ";
cout<<"\n";//没有进行过p++的才能用这种方式,因为上面进行了三次p++,p此时指向的是最后一个
}//为了规避这种情况我们利用指针回指打印数据
delete []p;
p=NULL;//注意如果用了p--指向第一个数据的话不能用delete,因为此时delete的不是我们申请的内存,
如果是这种情况使用p++指向到申请的内存在释放
system("pause");
return 0;
}
三、指向对象的指针
对象指针的用法:定义对象指针的语法和定义其它基本数据类型指针的语法相同。在使用对象指针之前,要把它指向一个已经创建的对象,然后才能访问该对象的成员。在使用对象名来访问对象成员时,要使用点运算符“.”。如果要通过指向对象的指针来访问对象的成员,那么必须使用箭头运算符“->”。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/158165.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...