zoukankan      html  css  js  c++  java
  • C++学习随笔之八:抽象与建模类的设计技术

    引言:本章的重点是类的设计技术,而不是通用原理
    1.操作符(运算符)重载:
    操作符重载本质(实质上)是一个函数(方法),不能重载基本类型的运行。语法为:
    void operator+(const  classs & i);
    class c;
    c.operator+(const class & i);//说明operator+ 就是个函数即: operator+()
    几乎可以重载所有的c操作符,但是也有其限制,主要有以下一些限制:
    (1)重载后的操作符必须至少有一个操作数是用户定义类型,这将防止用户为标准类型重载操作符
    (2)使用操作符时不能违反操作符原来的语法规则,也不能修改操作符的优先级。
    (3)不能定义不存在的操作符或新的操作符
    (4)以下几个操作符不能重载:
    sizeof——sizeof操作符
    .——成员操作符
    .*——成员指针操作符
    ::——作用域解析操作符
    ?:——条件操作符
    typeid——一个RTTI操作符
    const_cast——强制类型转换操作符
    dynamic_cast——强制类型转换操作符
    reinterpret——强制类型转换操作符
    static_cast——强制类型转换操作符
     
    可被重载的操作符如下表:
                                            可被重载的操作符
    (5)在上表中的大多数操作都可以通过成员或非成员函数进行重载,但下面的操作符只能通过成员函数来重载:
    =——赋值操作符
    ()——函数调用操作符
    []——下标操作符
    ->——通过指针访问类成员的操作符
    2.友元函数
    语法:在友元函数的声明中需要关键字friend ,而定义中不需要friend。虽然友元函数不是成员函数,但是它却与成员函数的访问权限一样。
    知道了友元函数后,你可能以为友元破坏了OOP的数据隐藏原则,其实不然,而应该将友元看做一种类的扩展接口,它和类方法只是表达类接口的两种不同机制。
    提示:如果要为类重载操作符,并将非类的项作为其第一个操作数,则可以用友元函数来反转操作数的顺序。
    一般来说要重载<<操作符来显示c_name的对象,可使用一个友元函数,定义如下:
    ostream & operator<<(ostream & os,const c_name & object)
    {
        os<<...;//显示对象内容
        return os;
    }
    代码示例:
    mytime3.h文件代码:
    #include<iostream>
    using namespace std;
    class Time
    {
        private:
            int hours;
            int minutes;
        public:
            Time();
            Time(int h,int m=0);
            void AddMin(int m);
            void AddHr(int h);
            void Reset(int h=0,int m=0);
            Time operator+(const Time & t)const;
            Time operator-(const Time & t)const;
            Time operator*(double n)const;
            friend Time operator*(double m,const Time & t)
            {
                return t*m;//调用operator*(double n)cosnt  成员函数 
            };
            //<< 操作符重载,友元函数的应用 ,用<<操作符重载来显示 Time 对象的内容 
            friend ostream & operator<<(ostream & os ,const Time & t);
    };
    mytime3.cpp文件代码:
    #include<iostream>
    #include "mytime3.h"
    using namespace std;

    Time::Time()
    {
        hours=minutes=0;
    }
    Time::Time(int h,int m)
    {
        hours = h;
        minutes = m;
    }
    void Time::AddHr(int h)
    {
        hours +=h;
    }
    void Time::AddMin(int m)
    {
        minutes +=m; 
    }
    void Time::Reset(int h,int m)
    {
        hours = h;
        minutes  =m ;
    }
    Time Time::operator+(const Time & t)const
    {
        Time sum;
        sum.minutes = minutes + t.minutes;
        sum.hours = hours+t.hours+ sum.minutes/60;
        sum.minutes %=60;
        return sum;
    }
    Time Time::operator-(const Time & t)const
    {
        Time diff;
        int tot1,tot2;
        tot1=t.minutes +60*t.hours;
        tot2=minutes + 60*hours; 
        diff.minutes = (tot2-tot1)%60;
        diff.hours = (tot2-tot1)/60;
        return diff;
    }
    Time Time::operator*(double mult)const
    {
        Time result;
        long totalMinutes = hours*mult*60 + minutes*mult;
        result.hours = totalMinutes/60;
        result.minutes = totalMinutes%60;
        return result;
    }
    //<< 操作符重载,友元函数的应用 ,用<<操作符重载来显示 Time 对象的内容 
    ostream & operator<<(ostream & os,const Time & t)
    {
        os << t.hours << " hours, "<< t.minutes << " minutes";
        return os;
    }
    usetime3.cpp文件代码(主文件):
    #include <cstdlib>
    #include <iostream>
    #include "mytime3.h"
    using namespace std;
    int main()
    {
        Time aida= Time(3,35);
        Time tosca = Time (2,48);
        Time temp;
        cout <<"Aida and Tosca:\n";
        cout << aida << "; " <<tosca <<endl;
        temp = aida + tosca;
        cout << "Aida + Tosca: "<<temp <<endl;
        temp = aida - tosca;
        cout <<"Aida - Tosca: " <<temp <<endl;
        temp = aida * 1.17;
        cout <<"Aida * 1.17: " <<temp<<endl;
        cout <<"10 * Tosca: "<<10*tosca <<endl;
        getchar();
        return 0; 
    }
    以上三个代码编译连接运行结果如下:

    3.随即数函数 srand()和rand():
    先从随机数的原理谈说起吧,   计算机的随机数都是由伪随机数,即是由小M多项式序列生成.产生每个小序列都有一个初始值,即随机种子.     srand()产生随机种子.     rand()产生随机数      srand()的函数定义为:void srand( unsigned int seed );要保证计算机产生不相同的随机数,应保证它们的随机种子是不一样的.srand((unsigned)time(NULL));就是以时间做为随机种子,因为每次你运行的时间总是不一样的. 也就是说 如果seed种子一样的话,用rand产生的随即数序列是一样的,故一般为了获取真正的随机数,所以采用时间做为srand()的种子。
    代码示例:
    #include<iostream>
    using namespace std;
    #include<cstdlib>
    int main()
    {
        srand(time(0));   
         for(int  i = 0; i < 10; i++ )      
         cout<<"随机数#"<<i <<": "<<rand()%20<<endl; //产生0-19之间的随机数
         getchar();
         return 0;
    4.类的自动转换和强制类型转换
    转换函数:是用户定义的强制类型转换,可以像使用强制类型转换那样使用,语法:operator typeName();typeName为要转换类型,比如说要将某类型转换为double 类型:operator double();但是转换函数必须满足一下三点:
    a.转换函数必须是类方法
    b.转换函数不能指定返回类型
    c.转换函数不能有参数
    当类定义了两种或者以上的转换函数时,通常使用显式调用转换函数,这样函数还能执行。
     
    5.众所周知,所以可执行程序执行的第一个函数是main函数,但是有没有什么方法是得在main函数之前执行其他函数呢?答案是肯定的。全局对象(即具有文件作用域的对象)就可以实现这种技术,因为全局对象将在程序的main函数被调用之前创建,程序员可以创建一个类,其默认构造函数将调用所有的构造函数里的函数。代码示例:
    class BeforeMain
    {
        private:
        //..
        public:
            BeforeMain()
            {
                GetData();
                ...    
              }
    };
    BeforeMain  test;
    int main()
    {
        ....
        return 0;
    }
    6.小结:下面是一个复数运算的程序源代码,里面覆盖了 重载,友元,类型转换,自动类型转换等技术里,是本章技术的综合应用。
    complex.h文件代码:
    #include<iostream>
    #include<cmath>
    using namespace std;

    class Complex
    {
        private:
            double r;
            double i;
        public:
            Complex();
            Complex(double real);
            Complex(double real,double imag);//复数 
            double Magnitude();//计算大小
            Complex operator+(const Complex & c)const;
            Complex operator-(const Complex & c)const;
            Complex operator~()const;
            friend Complex Square(const Complex & c);
            friend Complex operator*(const Complex & a,const Complex & b);
            friend ostream & operator<<(ostream & os,const Complex & c); 
            friend istream & operator>>(istream & is,Complex & c);
    };
    complex.cpp文件代码:
    #include<iostream>
    #include "complex.h"
    using namespace std;

    Complex::Complex()
    {
        r = i = 0.0;
    }
    Complex::Complex(double real)
    {
        r = real;
        i = 0.0;
    }
    Complex::Complex(double real,double imag)
    {
        r = real;
        i = imag;
    }
    double Complex::Magnitude()
    {
        return sqrt(r*r + i*i);
    }
    Complex Complex::operator+(const Complex & c)const
    {
        Complex add;
        add.r = r + c.r;
        add.i = i + c.i;
        return add; 
    }
    Complex Complex::operator-(const Complex & c)const
    {
        Complex sub;
        sub.r = r - c.r;
        sub.i = i - c.i;
        return sub;
    }
    Complex Complex::operator~()const
    {
        Complex c;
        c.r = r;
        c.i = -i;
        return c;
    }
    Complex Square(const Complex & c)
    {
        Complex square;
        square.r = c.r * c.r - c.i * c.i;
        square.i = 2.0 * c.r * c.i; 
        return square;
    }
    Complex operator*(const Complex & a,const Complex & b)
    {
        Complex mul;
        mul.r = a.r * b.r - a.i * b.i;
        mul.i = a.r * b.i + b.r * a.i;
        return mul;
    }
    ostream & operator<<(ostream & os ,const Complex & c)
    {
        os << "("<<c.r<<","<<c.i <<"i)";
        return os;
    }
    istream & operator>>(istream & is,Complex & c)
    {
        cout<<"real: ";
        if(is>>c.r)
        {
            cout<<"imaginary: ";
            is>>c.i;
        }
        return is;
    }

    主文件main函数文件代码:
    #include <cstdlib>
    #include <iostream>
    #include "complex.h"
    using namespace std;

    int main(int argc, char *argv[])
    {
        Complex a = Complex(3.0,4.0);
        Complex c ;
        cout<<"Enter a complex number(q to quit): "<<endl;
        while(cin>>c)
        {
            cout<<"c is "<< c<< endl; 
            cout<<"complex conjugate is " << ~c<<endl;
            cout <<"a + c is " << a + c << endl;
            cout <<"a - c is " << a - c << endl;
            cout <<"a * c is " << a * c <<endl;
            cout <<"2 * c is " << 2 * c <<endl;
            cout <<"c * 2 is " << c * 2 <<endl;
            cout <<"Enter a complex number(q to quit): "<<endl;     
        }
        cout << "Done!" <<endl;
        cin.get();
        return 0;
    }
  • 相关阅读:
    洛谷 1850 NOIP2016提高组 换教室
    2018牛客多校第三场 C.Shuffle Cards
    2018牛客多校第一场 B.Symmetric Matrix
    2018牛客多校第一场 A.Monotonic Matrix
    2018牛客多校第一场 D.Two Graphs
    2018宁夏邀请赛L Continuous Intervals
    2018宁夏邀请赛K Vertex Covers
    BZOJ
    HDU
    ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2015)
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964815.html
Copyright © 2011-2022 走看看