声明
学习材料: 侯捷老师 极客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; }
}
老师说检查学生写的类注意点
- 数据在private
- 参数尽可能引用,看情况const
- 返回值尽可能引用传递
- body本体中应该加const就要加(别人要不要用const都可以了)
- 初始化赋值尽量使用,尽量不要很晚了在{}内赋值
操作符重载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