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;
    }
  • 相关阅读:
    脚本性能分析
    openwrt补丁
    定制openwrt的根文件
    openwrt路由器更换了Flash之后需要修改的源码
    openwrt驱动与应用程序的联系
    我的vi/vim配置文件
    Python中的字典分组函数(groupby,itertools)
    迭代器
    tuple
    list
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964815.html
Copyright © 2011-2022 走看看