C++学习

主要参考侯捷——C++面向对象高级开发(上)(面向对象程序设计)学习笔记 - 知乎 (zhihu.com)

基础:

把构造函数放在private区:

class A {
public:
  static A& getInstance;
  setup(){......};
private:
  A()
  A(const A& rhs)
}

A& A::getInstance(){
  static A a ;
  return a;
}
//调用
A::getInstance().setup();

常量成员函数:

class JacobianAccumulator {
public:
    ..........

    /// get hessian matrix
    Matrix6d hessian() const { return H; }
    /// get bias
    Vector6d bias() const { return b; }
    /// get total cost
    double cost_func() const { return cost; }
    /// get projected points
    VecVector2d projected_points() const { return projection; }
    /// reset h, b, cost to zero
    void reset() {
        H = Matrix6d::Zero();
        b = Vector6d::Zero();
        cost = 0;
    }

private:
    ......
};

这是一个SLAM里面直接法的雅可比矩阵类,有三个函数 在()和{ }之间加了const ,是因为这三个函数不会改变返回值。

如果没加 在定义一个 const jacobianAccmulator J()时,认为我们不能随便改变J里面的参数,但是函数没加const,就认为可以。 

引用传递:

  • 参数传递,传递value是把整个参数全传过去,double4字节。尽量不要直接value传递。
  • 尽可能传递引用reference,传引用相当于传指针,很快,形式又很漂亮。
  • 传引用过去,修改之后,都会改变;如果只是为了提升速度,不向改变数据,那么传const引用。这样传进去的东西,不能被修改

操作符重载:

  • 第一种方式,写成成员函数。所有的成员函数都带有一个隐藏的参数this(是一个指针),this表示(指向)调用这个函数的调用者。
  • 定义函数的时候,在参数列中不能写出来this,直接用即可。

  • 传递者无需知道接受者是以引用形式接受。
  • 这里面虽然返回值需要的是引用(complex&),但是代码中写的返回值可以是value(*ths)。
  • +=操作符中,定义的参数是引用,但是传进去的c1也可以是value
  • 接收端使用什么形式接收与传递者无关。
  • 上面的操作符,进行操作之后,c2改变了,返回了c2的引用。因此感觉上,将操作符写为void函数也可以,但实际上,为了可以兼容c3+=c2+=c1的形式,写成返回引用更好。

  • 非成员函数的操作符重载。(没有this)
  • 应对客户的三种方法,写出三种方式,使用时进行重载。
  • 非成员函数是global函数。
  • 这些函数不能返回引用,必须是一个local object。因为这里面的操作符中二者不是一个加到另一个上,是两个对象相加,(加到哪没有说,前面加到哪明确),因此返回必须是一个对象,不是引用。
  • typename(),创建一个typename类型的临时对象。

构造函数和析构函数:

  • 字符串是一个指针,最后有结束符号\0。
  • 如果传入的是0,说明是空字符串,则只有一个结束符号。
  • 析构函数,释放指针指向的内存,类中有指针,析构函数要释放指针内存。

拷贝构造函数:

类中有指针,必须写拷贝构造和拷贝赋值,不然会内存泄漏。

  • 我们需要的是深拷贝。
  • 拷贝另一个string指针指向的字符串内容。
  • 必须保证const&,保证是引用传递,如果是值传递,会再一次调用拷贝构造函数,会发生无限递归。

再复制对象时要分为两个步骤:

第一步:开辟一个临时空间;

第二步:由于临时空间是需要构造的,重新调用拷贝构造函数(无穷递归形成…)

如果我们采用引用传参的方式,那么,在执行第二步时,不会调用复制构造函数,而是直接以地址的形式存储参数对象。即参数对象和新构建的对象地址相同。

拷贝赋值函数:

  • 拷贝赋值,两边目前都有东西。
  • 先检测是不是自我赋值,需要判断一下。
  • 然后先把数据清空,然后新建指定大小的数组。然后把字符串内容复制过来

Array new :

  • array new一定要搭配array delete,否则会内存泄漏。因为普通的delete只调用一次析构函数。内存泄漏会发生在剩下两个,因为剩下两个没有调用析构函数。
  • 这种情况主要发生在有指针的类,因为如果没有指针的类(比如之前的复数),没有动态分配内存new,因此也就不需要调用自己写的析构函数来杀掉。

static:

  • 在数据或函数前加static关键字,则变为静态函数/数据。
  • 一个成员函数要处理很多个数据,需要靠某个东西告诉他处理谁,就是this pointer。来告诉他处理从c1、c2、c3。成员函数有一个隐藏的this pointer参数。
  • 加上static之后,这个数据/函数就不属于这个对象了,跟这个对象脱离。
  • 静态函数没有this pointer参数,因此不能直接处理普通的对象,只能处理静态数据。

  • 这个例子中,利率mrate是静态数据,set_rate是静态函数。
  • 静态函数set_rate只能处理静态数据。
  • 静态函数可以通过对象object来调用,也可以通过class name来调用。

我们写的class只产生一个对象:

  • 构造函数放在private中,不想让外界创建。
  • 设计一个静态函数,来返回唯一的那一份,这个静态函数是外界取得这一份的唯一方法。
  • 调用这个静态函数之后,才开始创建这唯一的一份

class template:

  • 使用T来代替某种类型,类模板。
  • 使用的时候,<>中写明类型,编译器就会把T全部替换为这种类型。

  • 函数模板。
  • 这里面的min,比较的类型用T来表示。
  • 这样比较的时候,<符号就会使用T类型中重载的<符号来进行。
  • 用的时候不需要用<>绑定类型,编译器会根据传进去的对象类型自动绑定T类型

组合:

  • 表示这个class queue中,有一个这种sequence类东西。
  • 这个sequence是deque<T>
  • queue里面所有的功能,都是调用c的功能来完成的。

  • queue中有deque,deque的源代码中,还有另一个复合,Itr<T>。
  • 从内存的角度看,queue占用40字节。

  • 左边拥有右边。
  • 复合情况下的构造函数,由内而外,析构函数,由外而内。代码中红色的部分,是编译器来完成的。编译器会调用内部的默认的构造函数或析构函数。如果不希望调用默认的,那么就需要自己写代码。

  • 引用方式的复合,即左边has a右边类的指针。
  • 即可以通过该指针,把任务委托给右边的类。
  • 复合中,内部和外部是一起出现的,即调用二者的构造函数;而委托的话,因为是指针,是不同步的,当需要右边的时候,才创建这个。
  • 应用实例:右面的类为具体的实现,左边只是调用的接口。

继承:

  • 黄的的一行为使用public继承的语法,表示继承_List_node_base类。
  • 继承,表示is-a,是一种。
  • 父类的数据会被完整继承下来。
  • 子类拥有自己的以及父类的数据。

虚函数:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值