C++面向对象高级开发_极客班_第一节课笔记_section2

来源:互联网 发布:.cx域名投资 编辑:程序博客网 时间:2024/05/16 05:58

4.参数传递与返回值

参数传递与返回值是一个非常重要的内容。以前学习的时候没有体会到,这次听侯捷老师讲了之后,真的是醍醐灌顶。

4.1 构造函数的私有 与单例

calss A{public:    static A& getInstance();    setup(){};private:    A(){..}    A(const A& other){..}    int data;};A& A::getinstance(){  // 这里可以不写static    static A a;    return a;}

这就是一个单例。单例要求外部不可以通过调用构造函数的方式创建对象。这也是一个最基本的一个设计模式。至于其实现机制,以及static的作用,需要在之后的学习过程中具体展开。

4.2 常量成员函数const member functions

class complex{public:    complex(double r=0, double i = 0)    : re(r), im(i)    {}    double real() const { return re;}    double imag() const { return im;}private:    double re, im;};

所谓的常量成员函数 即:
double real() const { return re;}
其中最重要的就是 const

类的成员函数其实就分为两种,一种是能改变数据(data),另外一种是不能改变数据的。
那么,如果设计者,在设计类的成员函数时候,就要考虑,当这个函数调用类中的数据的时候,这个函数是改变类的数据,还是没有改变,如果没有改变,那么这个成员函数,就需要加const
这点非常重要!一定要内化

例如:用下面代码调用上面的类

const complex A(2,1);cout<< A.real();

如果double real() const { return re;}没有const,即 double real() { return re;},此时出现的情况是,编译错误。
原因:编译器会把不加const的成员函数当成可以修改类的成员变量的函数,这这与const complex A(2.1) 的const矛盾,因此会发出编译错误。

因此,一定要养成习惯,对不改变类的成员变量的成员函数要加const!

4.3 参数传递 pass by value & pass by reference( const)

在学习C语言的时候,大学里老师讲到参数传递的时候,一般都会讲一下基本语法,然后就是会十分强调当值传递(pass by value)的时候,是复制一个值,而不是直接传值。但是并没有从更深层次区分传值与传引用的区别。

C++是讲究效率的语言。因此,如果要追求效率的角度来讲, pass by value & pass by reference( const) 就会有十分大的区别。
因为,传值,如果是大于4个字节,那么就要把这个大的数据压到函数栈里面,效率就会变慢。而C语言,就是传指针,无论什么大小,直接传地址,通过传4个字节,提高了效率。而C++是用更漂亮的传引用的方式来传递,并且引用的底册实现机制也是指针,因此C++传引用的方式,也是速度快,并且代码表现很漂亮。

所以C++编程的原则之一就是: 不管什么参数传递,能用引用的都用引用传递。或者说,参数传递首先思考的就是引用传递
这句虽然说得很绝对,但是侯捷老师,建议初学者要尽量做到内化。
再一个,当对所需要传递的参数,当不需要改变参数的内容时,要时刻记得加const

ostream &operator << (ostream& os, const complex &x) {return os << '(' << x.real() << ',' << x.imag() << ')' <<endl;}

在这个例子中,由于要对输出流操作符 “<<”重载,因此,首先要判断参数传递是否可以用引用,然后在思考,传递的参数,在使用的过程中是否会发生改变,如果不发生改变,就要加const。

4.4 返回值传递 return by valuse & return by reference

返回值传递类型的选择也会影响C++的效率。总的原则,能进行返回值传递的尽量by reference

返回值类型的选择常常是实际编程中非常头疼的问题。
老师提供了一个思路,那就是
思考,函数最后返回的结果到底存放在哪里?这点很关键。如果是存放在已经有的空间(例如,存放在参数空间里),那就是返回引用;如果是需要另外开辟一个空间,那么,就需要传值了。

inlie complex&_doapls(complex* ths, const complex&r) {    ths.re += r.re;    ths.im += r.rm;    return *ths;}inlien complex&_add(complex& l, complex &r) {    complex temp;    temp.re = l.reag() + r.reag();    temp.im = l.imag() + r.imag();    return temp;}

由于第二个例子就是 传值,因为最后是 类的加的结果,要新开辟一个空间存放,因此需要传值。

4.5 C++编程的几个非常重要的注意点

  • 构造函数要用初始化列表初始化
  • 数据一定要存放在private里面
  • 成员函数调用成员变量,且不改变成员变量的时候要添加const
  • 传递参数的时候,要尽可能使用reference,另外就是如果不改变参数要加const
  • 返回值的处理,要尽量 return by reference.

4.6 friend 友元

class complex{public:    complex(double r=0, double i = 0)    : re(r), im(i)    {}    double real() const { return re;}    double imag() const { return im;}private:    double re, im;    friend complex& _doapls(complex* ths, const complex&r);};

友元,顾名思义,就是函数可以直接调用其数据,而无需通过成员函数来调用。
友元打破了C++封装的概念,因此,友元是有危险的。从设计者的考虑,友元的使用要尽量少。当然友元会有效率上的优势,具体还有看设计者的设计思路。

4.6 相同class的各个objects互为友元

class complex{public:    complex (double r = 0, double i = 0)    : re (r), im (i)    { }    int func(const complex& param)    { return param.re + param.im; }private:    double re, im;};{    complex c1(2,1);    complex c2;    c2.func(c1);}

这个例子就生动的表明了这个结论。因为C1,C2都是相同的类的对象,因此,C2可以直接通过func调用C1的数据,因为他们互为友元。

0 0
原创粉丝点击