• 学习C++.Primer.Plus 11 使用类


    1.操作符重载

    1. 重载操作符的几个限制:

      a)         重载的至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符。

      b)         不能违反操作符原有来的句法规则。

      c)         不能定义新的操作符。另外有一些操作符是不可以重载的,这里不列举。


    2.友元函数

    1. 创建友元函数:


      在类声明中加 friend 声明,在定义中不加friend,类的方法定义时加类名和限定符Time::,友元函数的定义则没有:

      //类声明中:
      friend Time operator* (double m, donst Time & t);
      
      //类的定义:不带 friend 标识符
      Time operator* (double m, const Time & t)
      {
          ...
      }
    2. 友元函数并没有违反OOP的数据隐藏原则,只有类声明可以决定哪一个函数是友元,因此类声明仍然控制了哪些函数可以访问私有数据。

    3. 常用的友元: 重载 << 操作符


      作为自定义Time类的友元:
      //声明:
      friend ostream & operator<< (ostream & os, const Time & t);
      //定义:
      ostream & operator<< (ostream & os, const Time & t)
      {
          ...
      }
    4. 在重载操作符时,使用友元函数和类方法不能重复,否则会被视为二义性错误,如下两个只能选择一个:

      //类方法:
      Time operator+ (const Time & t) const;
      //友元函数:
      friend Time operator+ (const Time & t1, const Time & t2);

    3.由一个矢量类引出的

    1. 如果方法计算得到了一个新的类对象,则应考虑是否可以使用类构造函数来完成这种工作。这样做不仅可以避免麻烦,而且可以确保新的对象是按照正确的方式创建的。

      Vector Vector::operator+ (const Vector & b) const
      {
          ...
          return Vector (.....);
      }
    2. 一元操作符重载:

      //声明
      Vector operator- () const;
      //定义
      Vector Vector::operator- () const
      {
          ...
      }
    3. 关于随机数:

      包含头文件 <stdlib>。

      标准 ANSI C库(C++中也有)中有一个rand()函数,返回从0到某个值之间的随机整数。rand()函数将一种算法用于一个初始种子值来获得随机数,该随机值将用作下一次函数调用的种子。因此产生的一系列的伪随机数。

      srand()函数允许覆盖默认的种子值,重新启动一个随机数序列。下面的程序在每次程序启动时都会设置不同的种子。(time(time_t)返回从某一时间开始的秒数,要引用<ctime>)

      srand(time(0 ) );

    4.类的自动转换和强制类型转换

    1. 只接受一个参数的构造函数定义了从参数类型到类类型的转换。如果使用关键字explicit限定了这种构造函数,则它只能用于显式转换,否则也可以用于隐式转换。

      //下面的构造函数只能用于显式转换
      explicit Stock(int n);
    2. 转换函数。下面是转换为double类型的转换函数:注意这里是不需要返回类型的,因为double名称已经指出的要返回的类型。

      另:关键字explicit不能用于转换函数。

      //声明。
      operator double();
      
      //定义
      Stock::operator double()
      {
          ...
          return double_val;
      }
    3. 提供转换函数时,应避免调用时的二义性。例如,下面的语句:

      long long_val = stock2;

      会在下面两个转换函数都存在时出错:

      operator int();
      operator long();
    4. (a)对于 Stock = Stock + Stock 的情况:

      可以提供方法定义 或者 友元函数 (只能同时提供一种)来实现:
      //类方法
      Stock operator+ (const Stock & stock1) const;
      //友元
      friend Stock operator+ (const Stock & stock1, const Stock & stock2);

      提供了上面的方法之后,如果还提供了Stock(double) 构造函数,还可以这么做:Stock = Stock + double;

      (b) 但对于 Stock = double + Stock 的情况,只有友元函数才可以。此时C++不会试图将double 转换成Stock类型,若将double 转换成Stock类型,那么double->Stock会变成调用成员函数的对象,因为C++只会对成员函数参数进行转换,而不会对调用成员函数的对象进行转换,所以不能这么做。
    5. 继续鉴于4中提到的问题,每次转换都要调用构造函数,假如要重载加法操作符,我们提供另一种方法,代码虽然多一点,但运行速度快。

      //成员方法
      Stock operator+ (double x);
      //友元函数
      friend Stock operator+ (double x, const Stock & stock);
    6. 在main方法之前插入调用函数的方法。

      定义一个全局对象(即文件作用域的对象):在这个对象的默认构造函数里加入要调用的函数部分。

     




  • 相关阅读:
    基于log4net的帮助类Log
    log4Net不能成功生成日志问题(关于配置错误)
    js 时间构造函数
    启动调试IIS时,vs无法在 Web 服务器上启动调试。Web 服务器未能找到请求的资源。 有关详细信息,请单击“帮助”。
    XmlException: 名称不能以“<”字符(十六进制值 0x3C)开头
    poj 3040 Allowance
    1144 数星星 (树状数组)
    18121 排排坐看电影
    18124 N皇后问题
    18025 小明的密码
  • 原文地址:https://www.cnblogs.com/yuantf/p/3303613.html
Copyright © 2020-2023  润新知