{C++系列} C++基础 day06 成员指针,操作符重载,
in C/C++ with 0 comment

{C++系列} C++基础 day06 成员指针,操作符重载,

in C/C++ with 0 comment

#复习:

1 拷贝构造和拷贝赋值

2 静态成员(static)

3 单例模式


#十九 成员指针(了解)

1 成员变量指针

1)定义

类型 类名::* 成员变量指针名 v= &类名::成员变量;

2)使用

对象.*成员变量指针名;

".*":成员指针解引用运算符

对象指针->*成员变量指针名;

"->*":间接成员指针解引用运算符。

注:成员变量指针的本质就是保存指定成员在对象中的相对地址。

#举例

成员指针举例

#include <iostream>
#include <cstdio>
using namespace std;

class Student{
public:
    Student(const string& name):m_name(name){}
    int m_no;
    int m_age;
    string m_name;
};
int main(void)
{
    string Student::*pname = &Student::m_name;
    Student s1("张飞");
    Student *ps2 = new Student("赵云");
    cout << s1.*pname << endl;
    cout << ps2->*pname << endl;

    printf("pname=%p\n",pname);
    printf("&s1=%p\n",&s1);
    printf("&s1.m_name=%p\n",&s1.m_name);
    return 0;
}

2 成员函数指针

1)定义

返回类型 (类名::*成员函数指针)(形参表)= &类名::成员函数名;

2)使用

(对象.*成员函数指针)(实参表)
(对象指针->*成员函数指针)(实参表)

#举例

成员函数指针举例

#include <iostream>
#include <cstdio>
using namespace std;

class Student{
public:
    Student(const string& name):m_name(name){}
    void who(void){
        cout << m_name << endl;
    }
    string m_name;
};
int main(void)
{
    void (Student::*pwho)(void) = &Student::who;
    Student s1("张飞");
    Student *ps2 = new Student("赵云");
    (s1.*pwho)();
    (ps2->*pwho)();
    return 0;
}

====================

#二十 操作符重载

eg:复数(x+yi)
   (1+2i) + (3+4i) = (4+6i)

1 双目操作符 L#R

1.1 运算类双目操作符:+ - * /

1)成员函数形式//推荐

L#R的表达式会被编译器翻译成L.operator#(R)成员函数的调用形式,该函数返回值即为表达式的结果。

2)全局函数形式

L#R表达式也可被编译器翻译成operator#(L,R)全局函数的调用形式,该函数返回值即为表达式的结果。

注:通过friend关键字,可以把一个全局函数声明为某个类的友元,友元函数可以访问类中的任何成员。

#举例

双目操作符重载举例

#include <iostream>
using namespace std;

int g = 100;
int& foo(void){
    return g;
}
class A{};
/*const*/ A hum(void){
    A a;
    return a;
}

int main(void)
{
    A a2;
    //hum().operator=(a2)
    hum() = a2;

    foo() = 200;

    int a = 10;
    cout << ++a << endl;//11
    cout << a << endl;//11
    cout << ++(++(++a)) << endl;
    cout << a << endl;
    ++a = 20;
    cout << a << endl;//20

    cout << a-- << endl;//20
    cout << a << endl;//19
    //a-- = 30;//error

    a = 30;
    int b = 40;
    //(a + b) = 50

    cout << (a=b) << endl;//40
    cout << a << endl;//40

    (a = b) = 50;//ok
    cout << a << endl;//50
}

1.2 赋值类双目操作符

1)成员函数形式

L#R--》L.operator#(R)

2)全局函数形式

L#R--》operator#(L,R)

#举例

运算符重载举例

#include <iostream>
using namespace std;
class Complex{
public:
    Complex(int r,int i):m_r(r),m_i(i){}
    void print(void)const{
        cout << m_r << '+' << m_i << 'i' << endl;
    }
    //c1+c2==>c1.operator+(c2)
    //三个const作用:
    //1)修饰返回结果,返回右值
    //2)修饰参数,支持常量型右操作数
    //3)常函数,支持常量型左操作数
    const Complex operator+(
            const Complex& c)const{
        Complex res(m_r+c.m_r,m_i+c.m_i);
        return res;
    }
private:
    int m_r;//实部
    int m_i;//虚部
    //将operator-声明为当前类的友元
    friend const Complex operator-(
        const Complex& l,const Complex& r);
};
//c2 - c1 ==> operator-(c2,c1);
const Complex operator-(
    const Complex& l,const Complex& r){
    Complex res(l.m_r-r.m_r,l.m_i-r.m_i);
    return res;
}

int main(void)
{
    const Complex c1(1,2);
    Complex c2(3,4);
    c1.print();
    c2.print();
    //Complex c3 = c1.operator+(c2);
    Complex c3 = c1 + c2;
    c3.print();//4+6i

    //c3 = operator-(c2,c1)
    c3 = c2 - c1;
    c3.print();//2+2i
    return 0;
}

#举例

运算符重载举例

#include <iostream>
using namespace std;
class Complex{
public:
    Complex(int r,int i):m_r(r),m_i(i){}
    void print(void)const{
        cout << m_r << '+' << m_i << 'i' << endl;
    }
    //c1+=c2 ==>c1.print()
    Complex& operator+=(const Complex& c){
        m_r += c.m_r;
        m_i += c.m_i;
        return *this;
    }
    //友元函数可以直接定义在类的内部,但是本质
    //还是全局函数,不属于类,没有this指针
    friend Complex& operator-=(
            Complex& l,const Complex& r){
        l.m_r -= r.m_r;
        l.m_i -= r.m_i;
        return l;
    }
private:
    int m_r;//实部
    int m_i;//虚部
};
int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);
    //c1.operator+=(c2)
    c1 += c2;
    c1.print();//4+i
    //operator-=(c1,c2)
    c1 -= c2;
    c1.print();//1+2i
    return 0;
}

2 单目操作符重载 #O

2.1 计算类单目操作符:~ -(负) !

2.2 自增减单目操作符

1)前缀自增减:

--》表达式结果是左值,就是操作数自身
--》操作数只能是左值

成员函数形式:
#O ==> O.operator#();
全局函数形式:
#O ==> operator#(O);

举例

单目运算符重砸

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(int i = 0):m_i(i){}
    void print(void)const{
        cout << m_i << endl;
    }
    //成员函数形式实现:-(负)
    //-i ==> i.operator-()
    const Integer operator-(void)const{
        Integer res(-m_i);
        return res;
    }
    //全局函数形式实现:~,自定义表示乘方
    friend const Integer operator~(
            const Integer& i){
        Integer res(i.m_i * i.m_i);
        return res;
    }
private:
    int m_i;
};
int main(void)
{
    Integer i(100);
    Integer j = -i;//i.operator-();
    j.print();//-100
    j = ~i;//operator~(i)
    j.print();//10000
    return 0;
}

2)后缀自增减:

成员函数形式:
O# ==> O.operator#(int);
全局函数形式:
O# ==> operator#(O,int);

#举例

自增运算符重载

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(int i = 0):m_i(i){}
    void print(void)const{
        cout << m_i << endl;
    }
    //前++,成员函数形式
    //++i==>i.operator++()
    Integer& operator++(void){
        ++m_i;
        return *this;
    }
    //前--,友元函数形式
    friend Integer& operator--(Integer& i){
        --i.m_i;
        return i;
    }
    //后++,成员函数形式
    //i++ ==> i.operator++(0)
    const Integer operator++(int){
        Integer old = *this;
        ++m_i;
        return old;
    }
    //后--,友元函数形式
    friend const Integer operator--(Integer& i,int){
        Integer old = i;
        --i.m_i;
        return old;
    }
private:
    int m_i;
};
int main(void)
{
    Integer i(100);
    Integer j = ++i;//i.operator++()
    i.print();//101
    j.print();//101
    j = ++++++i;
    i.print();//104
    j.print();//104
    
    j = i++;//i.operator++(0)
    i.print();//105
    j.print();//104

    j = --i;//operator--(i);
    i.print();//104
    j.print();//104

    j = ------i;
    i.print();//101
    j.print();//101

    j = i--;//operator--(i,0)
    i.print();//100
    j.print();//101

    return 0;
}

3 插入/提取操作符重载: << >>

功能:实现自定义的直接输入和输出
注:只能用全局函数形式(friend)

#include <iostream>
ostream//标准输出流类
istream//标准输入流类

ostream cout;
cout << a;//operator<<(cout,a)
istream cin;
cin >> a;//operator>>(cin,a)

friend ostream& operator<<(
    ostream& os,const RIGHT& right){...}
friend istream& operator>>(
    istream& is,RIGHT& right){...}

#举例

插入运算符重载

 #include <iostream>
using namespace std;
class Complex{
public:
    Complex(int r,int i):m_r(r),m_i(i){}
    //cout << c1 ==> operator<<(cout,c1)
    friend ostream& operator<<(
        ostream& os,const Complex& c){
        os << c.m_r << '+' << c.m_i << 'i';
        return os;
    }
    //cin >> c1 ==> operator>>(cin,c1)
    friend istream& operator>>(
        istream& is,Complex& c){
        is >> c.m_r >> c.m_i;
        return is;
    }
private:
    int m_r;//实部
    int m_i;//虚部
};
int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);
    cout << c1 << endl;
    cout << c1 << ',' << c2 << endl;
    cout << "请输入两个复数:" << endl;
    cin >> c1 >> c2;
    cout << c1 << ',' << c2 << endl;
    return 0;
}

============================

#练习:

实现3X3矩阵类,支持如下操作符

扩展: =

要求:除了"<<"其它都用成员函数形式

1 2 3   9 8 7   10 10 10
4 5 6 + 6 5 4 = 10 10 10
7 8 9   3 2 1   10 10 10

1 2 3   9 8 7   -8 -6 -4
4 5 6 - 6 5 4 = -2  0  2
7 8 9   3 2 1    4  6  8

1 2 3   9 8 7   30  24  18
4 5 6 * 6 5 4 = 84  69  54
7 8 9   3 2 1   138 114 90

    1 2 3    -1 -2 -3
 - 4 5 6 =  -4 -5 -6
    7 8 9    -7 -8 -9

class M33{
public:
    M33(void){
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                m_a[i][j] = 0;
    }
    M33(int a[][3]){
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                m_a[i][j] = a[i][j];
    }
    //eg:成员函数形式”+“
    const M33 operator+(const M33& m)const{
        int res[3][3] = {0}
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                res[i][i] =
                    m_a[i][j] + m.m_a[i][j];
        return M33(res);
    }
private:
    int m_a[3][3];
};
int main(void)
{
    int a1[3][3] = {1,2,3,4,5,6,7,8,9};
    int a2[3][3] = {9,8,7,6,5,4,3,2,1};
    M33 m1(a1);
    M33 m2(a2);
    m1 + m2;//m1.operator+(m2)
}

代码实现

#include <iostream>
#include <iomanip>
using namespace std;

class M33{
public:
    M33(void){
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                m_a[i][j] = 0;
    }
    M33(int a[][3]){
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                m_a[i][j] = a[i][j];
    }
    friend ostream& operator<<(
        ostream& os,const M33& m){
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++)
                //setw(4):设置域宽
                os << setw(4) << m.m_a[i][j];
            os << endl;
        }
        return os;
    }
    //+ - *:返回右值,操作数可以左值也可以是右值
    const M33 operator+(const M33& m)const{
        int a[3][3] = {0};
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                a[i][j] = m_a[i][j]+m.m_a[i][j];
        return M33(a);
    }
    const M33 operator-(const M33& m)const{
        int a[3][3] = {0};
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                a[i][j] = m_a[i][j]-m.m_a[i][j];
        return M33(a);
    }
    const M33 operator*(const M33& m)const{
        int a[3][3] = {0};
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                for(int k=0;k<3;k++)
                    a[i][j] += 
                        m_a[i][k]*m.m_a[k][j];
        return M33(a);
    }
    //+= -= *=,返回左值就是左操作数,
    //右操作数可以左值也可以是右值
    M33& operator+=(const M33& m){
        *this = *this + m;
        return *this;
    }
    M33& operator-=(const M33& m){
        *this = *this - m;
        return *this;
    }
    M33& operator*=(const M33& m){
        *this = *this * m;
        return *this;
    }
    //-(负):返回右值,操作数可左值也可右值
    const M33 operator-(void)const{
        //M33():以无参方式构建临时(匿名)对象
        return M33() - *this;
    }
    //前++/--:返回左值,就是操作数自身
    M33& operator++(void){
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                ++m_a[i][j];
        return *this;
    }
    M33& operator--(void){
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                --m_a[i][j];
        return *this;
    }
    //后++/--:返回右值,是操作数自增减前的副本
    const M33 operator++(int){
        M33 m = *this;
        ++(*this);
        return m;
    }
    const M33 operator--(int){
        M33 m = *this;
        --(*this);
        return m;
    }

private:
    int m_a[3][3];
};
int main(void)
{
    int a1[3][3] = {1,2,3,4,5,6,7,8,9};
    M33 m1(a1);
    int a2[3][3] = {9,8,7,6,5,4,3,2,1};
    M33 m2(a2);
    cout << m1 << endl;
    cout << m2 << endl;

    cout << "m1+m2:" << endl;
    cout << (m1+m2) << endl;
    cout << "m1-m2:" << endl;
    cout << (m1-m2) << endl;
    cout << "m1*m2:" << endl;
    cout << (m1*m2) << endl;

    cout << "m1+=m2:" << endl;
    cout << (m1+=m2) << endl;
    cout << m1 << endl;
    cout << "m1-=m2:" << endl;
    cout << (m1-=m2) << endl;
    cout << m1 << endl;
    cout << "m1*=m2:" << endl;
    cout << (m1*=m2) << endl;
    cout << m1 << endl;

    cout << "-m2:" << endl;
    cout << -m2 << endl;

    cout << "++m2:" << endl;
    cout << ++m2 << endl;
    cout << m2 << endl;
    cout << "--m2:" << endl;
    cout << --m2 << endl;
    cout << m2 << endl;
    cout << "m2++:" << endl;
    cout << m2++ << endl;
    cout << m2 << endl;
    cout << "m2--:" << endl;
    cout << m2-- << endl;
    cout << m2 << endl;
    return 0;

}
Responses