Cpp Primer<<学习函数-局部对象、内联函数、类的成员函数_1

函数

<局部对象>
在C++语言中,每个名字都有作用域,而每个对象都有生命期。名字的作用域指的是知道该名字的程序文本区。对象的生命期则是程序执行过程中对象存在的时间。
<<自动对象>>
自动变量(对象):只有定义它的函数被调用是才存在的对象成为自动对象。

void fun(int arg)
{
    // arg  自动对象(变量)
    auto int num; //  自动变量(对象)
}

函数被调用,则自动对象将在栈中分配局部存储空间
函数调用结束,则自动对象就会被收回局部内存空间
<<静态局部变量>>
在定义变量时,使用static关键字即可将该变量定义为静态局部变量。
静态局部变量,一旦被创建并初始化为0,直到程序结束该对象才会被撤销并收回存储空间。

size_t count_calls()
{
    static size_t ctr; // 自动初始化为零值..value will persit across calls
    return ++ctr;
}
int main()
{
    for (size_t i = 0; i != 10; ++i)
    {
        cout << count_calls() << end;
    }
    return 0;
}

<内联函数>
在定义函数的时候,在返回类型前加上关键字inline即可将函数定义为内联函数。
普通函数调用:
调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复;复制实参;程序还必须转向一个新位置执行。
内联函数:则可以避免函数调用的开销。定义为内联函数,在程序中每一次调用点上都会”内敛地”展开。

inline shorterString(const string &s1,const string&s2)
{s1.size() < s2.size() ? s1 : s2}

调用时

cout << shorterString() << endl;

编译时将内联展开为:

cout << (si.size() < s2.size() ? s1 : s2) << endl;

内联函数应该放入头文件中定义,它的定义对编译器而言必须是可见的,以便编译器能够在调用点内敛展开该函数的代码。
在头文件中加入或修改内联函数是,使用了该头文件的所有源文件都必须重新编译。

<成员函数>
包含四部分:
函数返回类型、函数名、用逗号隔开的形参表(可为void)、包含在一对花括号里面的函数体。
函数原型提供了函数返回值的类型、函数的名字、传递实参的类型。函数体既可以在类中定义亦可以在类外定义。
扩展的类定义:

class Sales_item{
        public:
            //  operation on Sales_item objects
            double avg_price() const;
            bool same_isbn(const Sales_item &rhs) const
                { return isbn == rhs.isbn}

        private:
            std::string isbn;
            unsigned uints_sold;
            double revenue;
    };

定义成员函数的函数体
类的成员函数既可以在类的定义内定义也可以在类的定义外定义。编译器隐式地将在类内定义的成员函数当作内联函数。类的成员函数可以访问该类的private成员。
1.成员函数含有额外的、隐含的形参.

  • 调用成员函数,实际上是通过使用对象来调用
if(total.same_isbn(trans))
 成员函数的额外的、隐含的形参将该成员函数与调用该函数的对象捆绑在一起。这个额外的、隐含的形参就是this指针。

2.this指针的引入

  • 每个成员函数(除了static成员函数为)都有一个额外的、隐含的形参this指针。调用成员函数时,该形参将初始化为调用成员函数对象的地址。
total.same_isbn(trans);

则编译器将重写该函数如下:

Sales_item::same_isbn(&total,trans);

在此调用中,same_isbn成员函数中无前缀的isbn属于total对象。

3.const成员函数

  • 跟在成员函数形参表后面的const的作用:const改变了隐含this形参的类型,在调用total.same_isbn(trans)时,使之成为指向const
    Sales_item *类型的指针。
//This code is illegal:We may not explicitly define the this pointer.
//Note that this is a pointer to const because same_isbn is a const member.
    bool Sales_item::same_isbn(const Sales_item *const this,const Sales_item &rhs){
            return (this->isbn == rhs.isbn);
        }

该函数成为常量成员函数。
常量成员函数仅可以读取调用对象的数据成员,不可以修改对象的数据成员。
类似于

const int a = 2;
const int *p = &a; //const普通对象要求指向他们的指针、引用具有const属性

const对象、指向const对象的指针或引用只能用于调用其const成员函数,若尝试调用它们来调用的非const成员函数,则是错误的。

4.this指针的使用

  • this指针是隐式定义的,在成员函数中可以显示地使用this指针,但却不可以显示地define this 指针,实际上显示定义this指针也是非法。
bool same_isbn(const Sales_item &rhs) const{
            return (this->isbn == rhs.isbn);
        }

<< 类外定义成员函数 >>

  • 在类外定义成员函数需在函数返回类型与函数名之间使用类型名+作用域操作符(::)表明是该类的成员函数
type class_name::function_name(type args) const{
    /*your code*/   
}

形参表后面的const则反映了在类class_name中声明成员函数的形式。在任何函数定义中,返回类型和形参表必须和函数声明保持一致。对于成员函数同样适用。若函数被声明为const成员函数,则函数定义是形参表后面也必须有const。

<<类的构造函数>>

  • 特殊的成员函数—构造函数

    构造函数不同于普通成员函数,构造函数无返回值类型且与类同名,当创建类对象时,它被用于初始化类对象的数据成员。初始化式来源于构造函数形参表中的初始化式。构造函数通常应确保其每个数据成员都完成初始化。

string str; /*default constructor:empty string*/
vector<int> ivec;/*default constructor:empty vector*/

vector的默认构造函数则生成一个没有元素的vector向量对象,当然也就不能通过下标对该对象进行赋值以及读取数据。
string 对象为类类型对象,将通过类类型提供的默认构造函数初始化为”\0”

  • 定义构造函数
    通常构造函数作为类的接口一部分。构造函数放在pulic部分,放入private中,则使该类没有太大的作用。它的定义可以放在类内定义,也可在类外定义,但是需要类名+作用域操作符(::)放在构造函数的名称前面指明该构造函数是该类的成员函数。
    在类中定义它:
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 constuctor needed to initialize members of built-in type
        Sales_item():units_sold(0),revenue(0.0){}
        //private member as before
        private:
            std::string isbn;
            unsigned units_sold;
            double revenue;
    };
  • 构造函数的初始化列表

    在冒号和花括号之间的代码称为构造函数的初始化列表。它的初始化列表为类中的各个数据成员指定初值。基本数据类型,需显示地放在初始化列表中,类类型则可以不需要,可以由该对象所属的类的默认构造函数进行该对象的初始化。

  • 合成的构造函数
    由编译器创建的默认构造函数则称为合成的构造函数,其将依据变量初始化的规则初始化类中的所有成员。

    变量初始化规则:
    1.在全局作用域中定义一个对象,则自动初始化为0
    2.使用static关键字定义一个静态局部对象,则自动初始化为0
    3.定义一个类类型对象,则该对象的初始化由该对象所属的类 提供的默认构造函数去完成。

    合成的默认构造函数一般适用于仅包含类类型成员的类,对于含有内置类型的数据成员,则需要我们显示地提供默认构造函数以及数据成员的初始化列表。

  • 类代码文件的组织

    类定义放入单独的头文件中,类名作为头文件的文件名,类中函数的定义也单独放入一个文件中,与类名同名
    Sales_item.h和Sales_item.cc。定义函数的文件中必须包含声明这个函数的头文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值