<<C++ Primer>>第七章读书笔记

  1. 函数不能返回另一个函数或者内置数组类型,但可以返回指向函数的指针,或指向数组元素的指针的指针
  2. 在定义或声明函数时,没有显式指定返回类型是不合法的:
    // error: missing return type 
    test(double v1, double v2) { /* ... */ } 
    早期的 C++ 版本可以接受这样的程序,将 test 函数的返回类型隐式地定义为 int 型。但在标准 C++ 中,上述程序则是错误的。
  3. 在调用函数时,如果该函数使用非引用的非 const 形参,则既可给该函数传递 const 实参也可传递非 const 的实参。因为初始化复制了初始化式的值,所以可用 const 对象初始化非 const 对象,反之亦然。令人吃惊的是,尽管函数的形参是 const,但是编译器却将 fcn 的定义视为其形码被声明为普通的 int 型:
    void fcn(const int i) { /* fcn can read but not write to i */ }
    void fcn(int i) { /* ... */ } // error: redefines fcn(int)
    这种用法是为了支持对 C 语言的兼容,因为在 C 语言中,具有 const 形参或非 const 形参的函数并无区别。
  4. 应该将不需要修改的引用形参定义为 const 引用。普通的非 const 引用形参在使用时不太灵活。这样的形参既不能用 const 对象初始化,也不能用字面值或产生右值的表达式实参初始化。
  5. 编译器忽略为任何数组形参指定的长度
  6. 和其他类型一样,数组形参可声明为数组的引用。如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。在这种情况下,数组大小成为形参和实参类型的一部分。编译器检查数组的实参的大小与形参的大小是否匹配:
    // ok: parameter is a reference to an array; size of array is fixed
    void printValues(int (&arr)[10]) { /* ... */ }
    int main()
    {
    	int i = 0, j[2] = {0, 1};
    	int k[10] = {0,1,2,3,4,5,6,7,8,9};
            printValues(&i); // error: argument is not an array of 10 ints
            printValues(j);  // error: argument is not an array of 10 ints
            printValues(k);  // ok: argument is an array of 10 ints
            return 0;
    }
  7. C++ 中的省略符形参是为了编译使用了 varargs 的 C 语言程序。关于如何使用 varargs,请查阅所用 C 语言编译器的文档。对于 C++ 程序,只能将简单数据类型传递给含有省略符形参的函数。实际上,当需要传递给省略符形参时,大多数类类型对象都不能正确地复制。
  8. 省略符形参有下列两种形式(在第一种形式中,形参声明后面的逗号是可选的):
    void foo(parm_list, ...);
    void foo(...);
  9. 返回引用的函数返回一个左值。因此,这样的函数可用于任何要求使用左值的地方:
    char &get_val(string &str, string::size_type ix)
    {
    	return str[ix];
    }
    int main()
    {
    	string s("a value");
            cout << s << endl;   // prints a value
            get_val(s, 0) = 'A'; // changes s[0] to A
    
            cout << s << endl;   // prints A value
            return 0;
    }
  10. 既可以在函数声明也可以在函数定义中指定默认实参。但是,在一个文件中,只能为一个形参指定默认实参一次。下面的例子是错误的:
    // ff.h
    int ff(int = 0);
    
    // ff.cc
    #include "ff.h"
    int ff(int i = 0) { /* ... */ } // error
    通常,应在函数声明中指定默认实参,并将该声明放在合适的头文件中。如果在函数定义的形参表中提供默认实参,那么只有在包含该函数定义的源文件中调用该函数时,默认实参才是有效的。
  11. inline 函数可能要在程序中定义不止一次,只要 inline 函数的定义在某个源文件中只出现一次,而且在所有源文件中,其定义必须是完全相同的。把 inline 函数的定义放在头文件中,可以确保在调用函数时所使用的定义是相同的,并且保证在调用点该函数的定义对编译器可见。
  12. 编译器隐式地将在类内定义的成员函数当作内联函数
  13. 现在,可以理解跟在 Sales_item 成员函数声明的形参表后面的 const 所起的作用了:const 改变了隐含的 this 形参的类型。在调用 total.same_isbn(trans) 时,隐含的 this 形参将是一个指向 total 对象的 const Sales_Item* 类型的指针。就像如下编写 same_isbn 的函数体一样:
    // pseudo-code illustration of how the implicit this pointer is used
    // This code is illegal: We may not explicitly define the this pointer ourselves
    // 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) const
    { return (this->isbn == rhs.isbn); }
    用这种方式使用 const 的函数称为常量成员函数。由于 this 是指向 const 对象的指针,const 成员函数不能修改调用该函数的对象。因此,函数 avg_price 和函数 same_isbn 只能读取而不能修改调用它们的对象的数据成员。 const 对象、指向 const 对象的指针或引用只能用于调用其 const 成员函数,如果尝试用它们来调用非 const 成员函数,则是错误的。
  14. 形参表后面的 const 则反映了在类 Sales_item 中声明成员函数的形式。在任何函数定义中,返回类型和形参表必须和函数声明(如果有的话)一致。对于成员函数,函数声明必须与其定义一致。如果函数被声明为 const 成员函数,那么函数定义时形参表后面也必须有 const。
  15. 值得注意的是,形参与 const 形参的等价性仅适用于非引用形参。有 const 引用形参的函数与有非 const 引用形参的函数是不同的。类似地,如果函数带有指向 const 类型的指针形参,则与带有指向相同类型的非 const 对象的指针形参的函数不相同。
  16. 一般的作用域规则同样适用于重载函数名。如果局部地声明一个函数,则该函数将屏蔽而不是重载在外层作用域中声明的同名函数。由此推论,每一个版本的重载函数都应在同一个作用域中声明。
    void print(const string &);
    void print(double);   // overloads the print function
    void fooBar(int ival)
    {
    	void print(int);   // new scope: hides previous instances of print
            print("Value: ");  // error: print(const string &) is hidden
            print(ival); // ok: print(int) is visible
            print(3.14); // ok: calls print(int); print(double) is hidden
    }
  17. 为了确定最佳匹配,编译器将实参类型到相应形参类型转换划分等级。转换等级以降序排列如下:
    • 精确匹配。实参与形参类型相同。
    • 通过类型提升实现的匹配(第 5.12.2 节)。
    • 通过标准转换实现的匹配(第 5.12.3 节)。
    • 通过类类型转换实现的匹配(第 14.9 节将介绍这类转换)。
  18. 这个语句将 pf 声明为指向函数的指针,它所指向的函数带有两个 const string& 类型的形参和 bool 类型的返回值。
    // pf points to function returning bool that takes two const string references
    bool (*pf)(const string &, const string &);
  19. 函数指针只能通过同类型的函数或函数指针或 0 值常量表达式进行初始化或赋值。
  20. 函数的形参可以是指向函数的指针。这种形参可以用以下两种形式编写:
    /* useBigger function's third parameter is a pointer to function
     * that function returns a bool and takes two const string references
     * two ways to specify that parameter:
     */
    // third parameter is a function type and is automatically treated as a pointer to function
    void useBigger(const string &, const string &,
                   bool(const string &, const string &));
    // equivalent declaration: explicitly define the parameter as a pointer to function
    void useBigger(const string &, const string &,
                   bool (*)(const string &, const string &));
  21. // ff is a function taking an int and returning a function pointer
    // the function pointed to returns an int and takes an int* and an int
    int (*ff(int))(int*, int);
  22. 允许将形参定义为函数类型,但函数的返回类型则必须是指向函数的指针,而不能是函数。具有函数类型的形参所对应的实参将被自动转换为指向相应函数类型的指针。但是,当返回的是函数时,同样的转换操作则无法实现:
    // func is a function type, not a pointer to function!
    typedef int func(int*, int);
    void f1(func); // ok: f1 has a parameter of function type
    func f2(int);  // error: f2 has a return type of function type
    func *f3(int); // ok: f3 returns a pointer to function type
  23. C++ 语言允许使用函数指针指向重载的函数:
    extern void ff(vector<double>);
    extern void ff(unsigned int);
    
    // which function does pf1 refer to?
    void (*pf1)(unsigned int) = &ff; // ff(unsigned)
    指针的类型必须与重载函数的一个版本精确匹配。如果没有精确匹配的函数,则对该指针的初始化或赋值都将导致编译错误:
    // error: no match: invalid parameter list
    void (*pf2)(int) = &ff;
    
    // error: no match: invalid return type
    double (*pf3)(vector<double>);
    pf3 = &ff;
    
     

转载于:https://www.cnblogs.com/cppfans/articles/2034540.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值