C++类和对象(2):对象(数组、指针)和拷贝构造函数

一.对象数组与数组指针

1.1对象数组

对象数组是指每一个数组元素都是对象的数组

定义一个一维数组的格式如下:

类名 数组名[下标表达式];

例:

A c[10];                                    //定义类A的对象数组c,含有10个对象数组元素

在建立数组时,有几个元素就调用几次数组元素。

在调用对象数组时,其一般形式为:
数组名[下标].成员名

在带一个参数的构造函数给对象数组赋值时,可以用大括号一次进行赋值。如:
 

A ob1[4]={11,22,33,44};              //类A的对象数组赋初值

如果构造函数有多个参数时,在定义数组时对其初始化的方式为

A ob1[4]=A(1,2),A(3,4),A(5,6)};            //类A的对象数组ob1赋初值

 同时,在定义数组时提供的参数不得超过数组元素的个数,如:

A ob1[4]={11,22,33,44,55};           //错误,实参格式超过对象数组的个数(构造函数只有一个参数)

1.2对象指针 

对象指针就是用来存放对象地址的变量。声明对象指针的一般语法形式为:

类名 *对象指针名;

1.3this指针

this指针:自引用指针

每当创建一个对象,系统就把this指针初始化为指向该对象,即this指针的值是当前调用成员函数的对象的起始地址。

例如:

假设有一个对象a的成员函数disp,再调用成员函数a.disp时,编译系统就把对象a的起始地址赋给this指针,于是在成员函数引用数据成员时,就按照this指针的指向找到对象a的数据成员。例如disp函数要输出数据成员x的值,实际上是在执行:
 

cout<<"x="<<this->x<<endl;

由于当前this指针指向对象a,因此相当于执行:

cout<<"x="<<a.x<<endl;

 这样就输出了对象a的数据成员x的值。

二.string类

使用string类必须在程序的开始包括头文件string,即要有如下语句:

#include<string>

string类的字符串对象也必须先定义后使用。定义格式如下:
string 对象1,对象2......; 

例如:

string str1,str2;                         //定义string类对象str1和str2

三.向函数传递对象

3.1使用对象作为函数的参数

对象可以作为参数传递给函数。在向函数传递对象时,是通过“传值调用”传递给函数的,即单向传递,只由实参传递给形参,而不能由形参传回来给实参。因此函数中对对象的任何修改均不影响调用该函数的对象(实参)本身

例如:

void sqr_it(Tr ob)               //对象ob作为函数sqr_it的形参

3.2使用对象指针作为函数的参数 

对象指针也可作为函数的参数。使用对象指针自我为函数的参数可以实现“传址调用”,即在函数调用时实参对象和形参对象指针变量指向同一内存地址。在函数调用的过程中,对形参对象指针所指对象值的改变也影响实参对象的值

例如:

void sqr_it(Tr *ob)        //对象指针作为函数的形参

3.3使用对象引用作为函数的参数

使用对象引用作为函数参数不但具有对象指针用作函数参数的优点,而且更简单直接。

例如:

void sqr_it(Tr &ob)                      //对象引用作为函数的形参

四.拷贝构造函数 

拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用。其作用是在建立一个新对象时,使用一个已经存在的对象去初始化这个新对象。例如

Point p2(p1);

其作用是,在建立新对象p2时,用已经存在的对象p1去初始化新对象p2,在这个过程中就要调用拷贝构造函数。 

4.1自定义拷贝构造函数

形式如下:
类名::类名(const 类名 &对象名)

{
        //拷贝构造函数的函数体

}

例如:

class Point
{
    public:
        Point(int a,int b)
        {
            x=a;
            y=b;
        }
        Point(const Point &p)                   //拷贝构造函数
        {
            x=2*p.x;
            y=2*p.y;
        }
        private:
            int x,y;
};

  调用拷贝构造函数的一般形式为:
类名 对象2(对象1);

或者

类名 对象2=对象1;

4.2默认拷贝构造函数

每一个类都必须要有一个拷贝构造函数。如果程序员没有定义拷贝构造函数,系统就会自动生成一个默认拷贝构造函数。

4.3调用拷贝构造函数的三种情况

(1)当用类的一个对象去初始化该类的另一个对象时,拷贝构造函数将会被调用。如:

Point p2(p1);       或        Point p2=p1;

(2) 当函数的形参是类的对象,在调用函数进行形参和实参结合时,拷贝构造函数将会被调用。如:

void fun1(Point p)
{
    p.print();
}
int main()
{
    Point p1(10,20);
    fun1(p1);                 //调用函数fun1时,实参p1是类Point的对象
    return 0;
}

(3)当函数的返回值是类的对象,在函数调用完毕将返回值(对象)带回函数调用处时。此时就会调用拷贝构造函数,将此对象复制给一个临时的对象并传送到该函数的调用处。例如:

Point fun2()                       //函数返回值类型是Point类类型
{
    Point p1(10,30);
    return p1;                     //函数的返回值类型是Point类的对象
}
int main()
{
    Point p2;
    p2=fun2();                     //函数调用完成,返回调用者时,调用拷贝构造函数
    return 0;
}

  五.静态成员

5.1静态数据成员

作用:实现同一个类多个数据成员之间的数据共享。

定义格式如下:、

static 数据类型 数据成员名;

如:

static int count;
static float sum;

 注:
(1)静态数据成员的定义与普通数据成员类似,但在前面要加上static关键字。

(2)静态数据成员的初始化应该在类外单独进行,而且应在定义对象之前进行,一般在主函数main之前,类声明之后的特殊地带来为他提供定义和初始化.初始化格式如下:
数据类型 类名::静态数据成员名=初始值;

例如:

int Student::count=0;
float Student::sum=0.0;

注意:这时候不要在数据成员名前面加static。

(3)静态数据成员属于类,可以用"类名::"访问静态数据成员。

格式如下:
类名::静态数据成员名

如:

Student::count;
Student::sum;

(4)静态数据成员和静态变量一样,是在编译时创建并初始化。他在该类的任何对象被建立之前就存在。因此,静态数据成员可以在对象定义之前被访问。对象定义之后,公有的静态数据成员也可以通过对象进行访问。用对象进行访问静态数据成员的格式如下:
对象名.静态数据成员名;

对象名->静态数据成员名;

5.2静态成员函数

定义静态成员函数的格式如下:

static 返回类型 静态成员函数名(参数表);

调用静态成员函数的方法有:

类名::静态成员函数名(实参表)

对象.静态成员函数名(实参表)

对象指针->静态成员函数名(实参表)

一般情况下,静态数据成员只用来访问静态数据成员。私有静态成员函数不能做类外部的函数和对象访问。

使用静态成员函数,可以用它在建立任何对象之前调用静态成员函数,以处理静态数据成员,这是普通函数不能实现的功能

如果在类外调用共有的静态成员函数,使用以下的格式较好:
类名::静态成员函数名()

静态成员函数和非静态成员函数的重要区别是:非静态成员函数有this指针,静态成员函数没有this指针

静态数据成员一般不访问类中的非静态成员。如果需要访问的话,静态数据成员只能通过对象名(或对象指针,对象引用)来访问该对象的非静态成员

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值