从复数类实现中看到精髓--面向对象高级开发学习系列

声明

学习材料: 侯捷老师 极客band的教程
笔记使用VScode写markdown
用sublime编译,因为VScode对于中文路径编译有问题
用csdn来作为快速图床

inline和宏

inline和宏差不多,方法直接写在定义的地方是inline
会很快,写在外面用inline关键字来标识,具体是否
inline取决于编译器实现

public,private

数据和私有数据处理一般放在private
public放给外界使用的接口

可以交错写,不一定只写成两段

构造函数

  • 可以默认值,当然其他函数也可以这样
  • 一般使用complex(double r=0,double i=0):re(r),im(i){}初始化列 里面写,这样写得很大气(在初始化列初始化)
  • 构建赋值由声明顺序决定
  • 没有返回类型—不过曾经学jni发现是返回类对象的指针
  • 可以有多个构造函数,可以重载(常用于构造函数),编译器会编码成不同的东西

但是以下两种会是编译器不知道怎么构造而发生冲突

public:
    complex(double r = 0, double i = 0)
        : re (r), im (i)
    { }
    complex () : re(0), im(0) { }

{
    // 下面会导致ambiguous
    complex a;
    complex b();
}
  • singleton单例设计模式把构造函数写在private(老师说暂时不深入)

不带指针的类和带指针的类

不带指针的类多半不用写析构函数

const member functions(常量成员函数)

不改变数据内容的,就加const关键字

一般只是返回数据

不写会怎样,看老师的例子,老师说很重要

正规,大师写法,鲁棒性更高

double real () const { return re; }

{
    const complex c1(2,1);
// 如果前面方法没有用const,而你定义的c1是const
// 这样你使用下面的输出编译器会报错
// 因为它以为你可能会改变c1中的值,所以不准
    cout<< c1.real();
    cout<< c1.imag();
}

pass by value vs. pass by reference

传值可能在size很大的时候会导致耗时很多

引用就好很多

C语言有指针传递

老师说引用的底部其实就是指针 4个字节

当然如果char 1个字节,也可以直接传值,但是为了统一
还是用引用比较好

然后就是如果不想别人改变你内容,你可以用
你改了就编译不过

complex& operator += (const complex&);

return by value vs. return by reference

为了效率,有些东西要成为习惯

返回值也尽量使用引用,如上面代码

如果要返回临时变量就不能传引用,因为临时变量在
函数结束之后自己会消亡掉

friend(友元)

友元可以取得private成员

朋友虽然打破了封装,但是可以直接引用数据,
函数调用获取数据就慢了

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

class complex{
public:

    // 这里没有通过函数拿,而是直接拿数据
    int func(const complex& param)
    { return param.re + param.im; }
}

老师说检查学生写的类注意点

  1. 数据在private
  2. 参数尽可能引用,看情况const
  3. 返回值尽可能引用传递
  4. body本体中应该加const就要加(别人要不要用const都可以了)
  5. 初始化赋值尽量使用,尽量不要很晚了在{}内赋值

操作符重载1–成员函数_有this

  • C++里面操作符就相当于一个函数,而C语言不是
  • 写个plus函数不好,所以C++容许你重载+
  • 谁调用我,谁就是this(写代码看不到this传参),任何成员函数都隐藏了this

return by reference

传参者无需知道接收者是以reference形式接收!

传参者无需知道接收者是以reference形式接收,你可以用reference接收,也可以用值传递接收

突然让我想到上次惨败的tx面试,函数传指针和引用有什么区别,现在看了侯捷老师的讲解才知道这么精妙
就是定义为指针的话,传递者也必须知道自己要传递的是指针,而如果是reference的话,传递者只需要知道自己传递一个对象就行了,绝妙的讲解啊

连串赋值

还因为有连串赋值,所以+=的返回值不设计成为void,而是complex&

上面3个小节对应的代码和图片看下面

inline complex&
__doapl(complex* ths, const complex& r)
{
    ...
    return *ths;
}


inline complex&
complex::operator += (const complex& r)
{
    return __doapl(this,r);
}

{
    complex c1(2,1);
    complex c2(5);

    c2 += c1;
    c3 += c2 += c1;
}

在这里插入图片描述

操作符重载2–非成员函数_无this

// 这里 加 的返回值应该是对象,不能传reference,否则传出去一个指针,然后内存回收掉了,然后就很奇怪了
// c = a + b;
inline complex
operator + (const complex& x, const complex& y)
{
    return complex(real(x) + real(y),
                   imag(x) + imag(y));
}

临时对象typename()

临时对象typename(),生命很短,用完就没了,上面那个函数中的complex()就是,临时

关于直接返回引用的测试代码

#include<bits/stdc++.h>
using namespace std;

// error: invalid initialization of reference of type 'int&' from expression of type 'const int'
//      return a;
//             ^

// 我试了一下,发现是不行的啊
// 等下,a变成了const int?!那应该就是说其实return之后应该也可以
// 变成int吧,难道老师说错了,待会试试复数类的东西吧

// 后面复习的时候突然想到了为什么这里不行了
// 因为这里a 已经变成了一个临时变量了?
// 然后自己尝试把const去掉,编译成功了
// 所以就是说接受者const,传参者随意
// 但是如果接受者不const,传参者不能const
// 这就是之前老师说的你设计的函数尽量加const!
// int & zheng(const int& a)
// {
//     return a;
// }
// 引用真香!!!!!

int & zheng(int& a)
{
    return a;
}

const int & zheng3(const int & a)
{
    return a;
}

int zheng2(const int& a)
{
    return a;
}

int main(){
    int a = 233;
    cout<< zheng(a)<<endl;
    cout<< zheng2(a)<<endl;
    cout<< zheng3(a)<<endl;

    return 0;
}

全部讲解用到代码

#ifndef __COMPLEX__
#define __COMPLEX__

// template<typename T>
class complex
{
public:
    complex (double r=0, double i=0)
        : re (r) ,im (i)
    { }

    complex& operator += (const complex&);
    double real () const { return re; }
    double imag () const { return im; }
private:
    double re, im;

    friend complex& __doapl (complex*,
                             const complex&);

};

inline complex&
__doapl(complex* ths, const complex& r)
{
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

inline complex &
complex::operator += (const complex & r)
{
    return __doapl (this, r);
}

inline complex
operator + (const complex& x, const complex& y)
{
    return complex (real(x) + real(y),
                    imag(x) + imag(y) );
}

inline complex
operator + (const complex& x, double y)
{
    return complex (real(x) + y, imag(x));
}

inline complex
operator + (double x, const complex& y)
{
    return complex (x + real(y), imag(y));
}

// 因为不考虑 c1 << cout; 所以无法使用成员函数定义
// 因为成员函数定义要用对象在左边
#include <iostream.h>
ostream&
operator << (ostream& os, const complex& x)
{
    return os << '(' << real (x) << ','
              << imag (x) << ')';
}

#endif
发布了41 篇原创文章 · 获赞 5 · 访问量 1万+
App 阅读领勋章
微信扫码 下载APP
阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览