原创 C++多态(4)——特殊运算符重载和类类型转换

2018-2-19 11:36 2108 33 33 分类: 软件与OS 文集: C++学习记录(1)

1.++”和“--”的重载

    运算符“++”和“--”的重载要区分前置和后置两种形式。如果不区分前置和后置,则使用operator++()operator—()即可,否则要使用operator++()operator--()重载前置运算符,使用operator++(int)operator--int)来重载后置运算符,调用时,参数int被传递值0

#include<iostream>

using namespace std;

class A

{

public:

    A(int x = 0):n(x){}

    int getn() { return n; }

    A operator++();

    A operator--(int);

private:

    int n;

};

A A::operator++()

{

    ++n;

    return *this;

}

A A::operator--(int)

{

    n--;

    return *this;

}

int main()

{

    A ob(3);

    cout << "ob.n= " << ob.getn() << endl;

    ++ob;

    cout << "ob.n= "<<ob.getn() << endl;

    ob.operator--(0);

    cout << "ob.n=" << ob.getn() << endl;

    system("pause");

    return 0;

}

 声明和定义后置“++”或“--”等运算符重载,必须含有参数形式,在调用时一般指定实参为0

 2. 赋值运算符“=”重载

对于任何一个类,如果没有用户自定义的赋值运算函数,系统会自动地生成一个默认的赋值运算函数,以完成数据成员之间的复制。

例如:

X  &X::operator=(const  X &source)

{

       类对象成员之间的赋值语句

}

     一旦类X的两个对象ob1ob2已创建,就可以用ob1=ob2进行赋值了。通常情况下,默认的赋值运算符函数可完成赋值任务,但在某些特殊的情况。类如,类中有一指针类的形式,如果使用默认的赋值运算符函数就会产生指针悬挂的错误。此时,就必须显式地定义一个赋值运算符重载函数,使参与赋值的两个对象有各自的存储空间。

#include<iostream>

#include<string>

using namespace std;

class Internet

{

public:

    char *name;

    char *url;

    Internet(char *name, char *url)

    {

        this->name = new char[strlen(name) + 1];

        this->url = new char[strlen(url) + 1];

        if (this->name)

        {

            strcpy(this->name, name);

        }

        if (this->url)

        {

            strcpy(this->url, url);

        }

    }

    Internet(Internet &temp)

    {

        this->name = new char[strlen(temp.name) + 1];

        this->url = new char[strlen(temp.url) + 1];

        if (this->name)

        {

            strcpy(this->name, temp.name);

        }

        if (url)

        {

            strcpy(this->url, temp.url);

        }

    }

    ~Internet()

    {

        delete[] name;

        delete[] url;

    }

    Internet & operator=(Internet &temp)

    {

        delete[] this->name;

        delete[] this->url;

        this->name = new char[strlen(temp.name) + 1];

        this->url = new char[strlen(temp.url) + 1];

        if (this->name)

        {

            strcpy(this->name, temp.name);

        }

        if (this->url)

        {

            strcpy(this->url, temp.url);

        }

        return *this;

    }

   

};

int main()

{

    Internet a("pxc", "www.pxc.jx.cn");

    Internet b = a;

    cout << b.name << endl << b.url << endl;

    Internet c("Tsinghua", "www.tsinghua.edu.cn");

    b = c;

    cout << b.name << endl << b.url << endl;

    system("pause");

    return 0;

}

 

  在上述代码中,在类对象还未存在的情况下,赋值过程通过拷贝构造函数进行;当对象已经存在,赋值过程就通过赋值运算符重载函数进行。在进行赋值运算符“=”的重载时,要注意赋值运算符只能重载为运算符成员函数,不能重载为友元运算符函数,而且赋值运算符重载后不能被继承。

 3.下标运算符“[]”的重载

    下标运算符通常用来访问数组中的某个元素,可以看做是一个双目运算符,第一个运算符是数组名,第二个运算符是数组下标。在类对象中,可以重载下标运算符,用它来定义相应对象的小标运算。它的定义如下:

T1 T::operator[](T2);

     其中,T是定义下标运算符的类,T2表示下标,其可以是任意类型,如整型,字符型或某个类。T1是数组运算的结果,可以是任意类型,但为了能对数组赋值,一帮将其声明为引用形式。在实际的程序中,可以通过下面两种方式来调用下标运算符:

X[y] x.operator[](y)

 

#include<iostream>

using namespace std;

class IntArray

{

public:

    IntArray(int size)

    {

        sz = size;

        a = new int[size];

    }

    int &operator[](int i)

    {

        if (i<0 || i>sz)

        {

            cout << "error" << endl;

            exit(1);

        }

        return a[i];

    }

    ~IntArray()

    {

        delete[]a;

    }

private:

    int *a;

    int sz;

};

int main()

{

    IntArray a(5);

    a[3] = 0;

    cout << "a[3]= " << a[3] << endl;

    a.operator[](3) = 0;

    cout << "a.operator[](3)= " << a[3] << endl;

    cout << "a[6]= ";

    a.operator[](6) = 6;

    system("pause");

    return 0;

}

下标越界则返回errorC++不允许把下标运算符函数作为外部函数来定义,只能是非静态的成员函数。


4.类类型转换

类类型转换是指某个对象的数据类型为类,而不是标准的数据类型。在C++中,标准的数据类型和类类型转换有三种方法。

(1)通过构造函数转换:可以将标准类型转换为类类型,但不能将类类型转换为标准类型;

(2)通过类类型转换函数转换:要将类类型转换为标准数据类型时,需要采用显示类型转换,定义类类型转换函数;

(3)通过运算符重载实现类型转换:可以实现标准类型的数据与类对象之间的运算。

 

C++中定义一个类的类型转换函数的形式为:

<类名>::operator type()

{

   Return type 类型的数据

}

其中type为要转换的目标类型,通常是标准类型。使用类类型转换函数时要注意:

(1)          此函数的功能是将类的对象转换为类型为type的数据,它既没有参数,也没有返回类型,但在函数体中必须返回具有type类型的一个数据;

(2)          类类型转换函数只能定义为类的成员函数;

(3)          一个类内可以定义多个类类型转换函数,编译器会根据操作数的类型自动选择一个合适的类类型转换函数与之匹配。但在可能出现二义性时,应显式地使用类类型转换函数进行转换。

在实际的使用中,使用最多的还是运算符重载来实现类型的转换,转换运算符的声明方式比较特别。

#include<iostream>

using namespace std;

class Test

{

public:

    int a;

    Test(int a = 0)

    {

        cout << this << ":" << "载入构造函数" << a << endl;

        Test::a = a;

    }

    Test(Test &temp)

    {

        cout << "拷贝构造函数" << endl;

        Test::a = temp.a;

    }

    ~Test()

    {

        cout << this << ":" << "析构函数" << this->a << endl;

        cin.get();

    }

    operator int()

    {

        cout << this << ":" << "转换运算符函数" << this->a << endl;

        return Test::a;

    }

};

int main()

{

    Test b(99);

    cout << "b内存地址:" << &b << endl;

    cout << (int)b << endl;

    system("pause");

    return 0;

}

       在上述代码中,利用转换运算符将Test类的对象强制转换为int类型并输出,此时观察转换运算符函数的运行状态,发现并没有产生临时对象,虽然它带有return 语句,但它与普通函数并不相同。

文章评论0条评论)

登录后参与讨论
我要评论
0
33
关闭 站长推荐上一条 /2 下一条