• 关于类的成员函数的一些学习


    举一个例子:

    class Sales_item {
         public:
             // operations on Sales_item objects
             double avg_price() const;
             bool same_isbn(const Sales_item &rhs) const
                  { return isbn == rhs.isbn; }
         // private members as before
         private:
             std::string isbn;
             unsigned units_sold;
             double revenue;
         };
    • 成员函数含有的隐含的参数

    调用成员函数时,实际上是使用对象来调用的。例如,调用  same_isbn,是通过名为 total 的对象来执行 same_isbn 函数的:

    if (total.same_isbn(trans))

    定义体如下:

    bool same_isbn(const Sales_item &rhs) const
             { return isbn == rhs.isbn; }

    在这个调用中,传递了对象 trans。作为执行调用的一部分,使用对象 trans 初始化形参 rhs。于是,rhs.isbntrans.isbn 的引用。而没有前缀的 isbn 使用了相同的实参绑定过程,使之与名为 total 的对象绑定起来。每个成员函数都有一个额外的、隐含的形参将该成员函数与调用该函数的类对象捆绑在一起。当调用名为 total 的对象的 same_isbn 时,这个对象也传递给了函数。而 same_isbn 函数使用 isbn 时,就隐式地使用了调用该函数的对象的 isbn 成员。这个函数调用的效果是比较 total.isbntrans.isbn 两个值。可以参看下下面将要讲到的this指针的使用。

    • this指针的引用

    每个成员函数都有一个额外的、隐含的形参 this。在调用成员函数时,形参 this 初始化为调用函数的对象的地址

    • const成员函数的引用

    跟在 Sales_item 成员函数声明的形参表后面的 const 所起的作用:const 改变了隐含的 this 形参的类型(即指针所指向的对象的数据不能够被更改)。在调用 total.same_isbn(trans) 时,隐含的 this 形参将是一个指向 total 对象的 const Sales_Item* 类型的指针。就像如下编写 same_isbn 的函数体一样:

    bool Sales_item::same_isbn(const Sales_item *const this,
                                   const Sales_item &rhs) const
         { return (this->isbn == rhs.isbn); }

    用这种方式使用 const 的函数称为常量成员函数由于 this 是指向 const 对象的指针,const 成员函数不能修改调用该函数的对象。因此,函数 avg_price 和函数 same_isbn 只能读取而不能修改调用它们的对象的数据成员

    const 对象、指向 const 对象的指针或引用(引用本身不是对象,所以引用本身没有const,只能是它指向的对象是const)只能用于调用其 const 成员函数,如果尝试用它们来调用非 const 成员函数,则是错误的

    在成员函数中,不必显式地使用 this 指针来访问被调用函数所属对象的成员。对这个类的成员的任何没有前缀的引用,都被假定为通过指针 this 实现的引用:

    bool same_isbn(const Sales_item &rhs) const
             { return isbn == rhs.isbn; }

    由于 this 指针是隐式定义的,因此不需要在函数的形参表中包含 this 指针,实际上,这样做也是非法的。但是,在函数体中可以显式地使用 this 指针。如下定义函数 same_isbn 尽管没有必要,但是却是合法的:

    bool same_isbn(const Sales_item &rhs) const
             { return this->isbn == rhs.isbn; }
    • 编写类的构造函数

    还必须编写一个成员,那就是构造函数。在定义类Sales_item时没有初始化它的数据成员,而是通过构造函数来初始化其数据成员。

    构造函数是特殊的成员函数,与其他成员函数不同,构造函数和类同名,而且没有返回类型。而与其他成员函数相同的是,构造函数也有形参表(可能为空)和函数体。一个类可以有多个构造函数,每个构造函数必须有与其他构造函数不同数目或类型的形参。构造函数的形参指定了创建类类型对象时使用的初始化式。通常,这些初始化式会用于初始化新创建对象的数据成员。构造函数通常应确保其每个数据成员都完成了初始化

    Sales_item 类只需要显式定义一个构造函数:没有形参的默认构造函数。默认构造函数说明当定义对象却没有为它提供(显式的)初始化式时应该怎么办,例如:

    vector<int> vi;       // default constructor: empty vector
         string s;             // default constructor: empty string
         Sales_item item;      // default constructor: ???

    我们知道 stringvector 类默认构造函数的行为:这些构造函数会将对象初始化为合理的默认状态。string 的默认构造函数会产生空字符串上,相当于 ""vector 的默认构造函数则生成一个没有元素的 vector 向量对象。同样地,我们希望类 Sales_items 的默认构造函数为它生成一个空的 Sales_item 对象。这里的“空”意味着对象中的 isbn 是空字符串,units_soldrevenue 则初始化为 0。

    和其他成员函数一样,构造函数也必须在类中声明,但是可以在类中或类外定义。由于我们的构造函数很简单,因此在类中定义它:

    class Sales_item {
         public:
             // operations on Sales_item objects
             double avg_price() const;
             bool same_isbn(const Sales_item &rhs) const
                 { return isbn == rhs.isbn; }
             // default constructor needed to initialize members of built-in type
             Sales_item(): units_sold(0), revenue(0.0) { }
         // private members as before
         private:
             std::string isbn;
             unsigned units_sold;
             double revenue;
         };

    对于定义本身:

    Sales_item(): units_sold(0), revenue(0.0) { }

    这个构造函数的形参表和函数体都为空。在冒号和花括号之间的代码称为构造函数的初始化列表。构造函数的初始化列表为类的一个或多个数据成员指定初值。它跟在构造函数的形参表之后,以冒号开关。构造函数的初始化式是一系列成员名,每个成员后面是括在圆括号中的初始值。多个成员的初始化用逗号分隔上述例题的初始化列表表明 units_soldrevenue 成员都应初始化为 0。每当创建 Sales_item 对象时,它的这两个成员都以初值 0 出现。而 isbn 成员可以不必准确指明其初值。除非在初始化列表中有其他表述,否则具有类类型的成员皆被其默认构造函数自动初始化。于是,isbnstring 类的默认构造函数初始化为空串。当然,如果有必要的话,也可以在初始化列表中指明 isbn 的默认初值。解释了初始化列表后,就可以深入地了解这个构造函数了:它的形参表和函数体都为空。形参表为空是因为正在定义的构造函数是默认调用的,无需提供任何初值。函数体为空是因为除了初始化 units_soldrevenue 成员外没有其他工作可做了。初始化列表显式地将 units_soldrevenue 初始化为 0,并隐式地将 isbn 初始化为空串。当创建新 Sales_item 对象时,数据成员将以这些值出现。

     

     

  • 相关阅读:
    搭建无线漫游网络及需要注意的问题
    手机如何借用笔记本网络上网
    VM下Linux网卡丢失(pcnet32 device eth0 does not seem to be ...)解决方案
    安装VMware vCenter过程设置数据库方法
    无法连接vCenter Server清单https://IP:10443
    ESXi控制台TSM:弥补vSphere Client不足
    Shell中逻辑判断
    bash 编程中循环语句用法
    Shell中IFS用法
    Shell中的${},##和%%的使用
  • 原文地址:https://www.cnblogs.com/predator-wang/p/5197453.html
Copyright © 2020-2023  润新知