GeekBand C++面向对象高级编程(上)第一周笔记

C++演进

最主要的两个版本 C++98(1.0)和C++11(2.0),C++14是在11的基础上做了一些小更新

C++学习分为语言和标准库两部分

语言部分书籍推荐
《C++ primer》
《The C++ program language》
《Effective C++》
标准库部分的书籍推荐
《C++ Standard Libiary》
《STL源码解析》

C VS C++

C: 主要包含数据和函数,通过函数去处理数据;数据都是全局的,每个函数都可以处理这个数据,这样带来的缺点是对后面的函数是有影响的
C++:通过class将数据和处理这个数据的函数放在一起,通过这个class创建出对象

C++ 关于数据和函数

class 分为带指针的和不带指针的,本门课程将通过complex和string这两个类的设计来分别说明。
complex 复数,数据部分包含实部和虚部两部分,复数需要支持加减乘除、共轭复数等等操作
string 字符串,数据是一个字符数组,其实是个指针,需要支持赋值、拷贝、附加、插入等操作

C++程序代码形式

包含一个以.h的头文件以及一个.cpp的主文件,同时也会用到标准库,标准库也是以头文件的方式include进来

#include

complex头文件

需要在头部通过define常量避免多次include,称作防卫式的申明,现在很多IDE在创建头文件时,会帮你自动生成,创建complex.h

#ifndef LEARNCPP_COMPLEX_H
#define LEARNCPP_COMPLEX_H
...
#endif //LEARNCPP_COMPLEX_H

代码主体部分主要包含前置申明以及类的申明和类的定义三部分,下面分别来设计
类的申明部分

class complex {  // class header部分
    // class body部分
    public:    // 可以通过类的实例使用
        complex(double r = 0, double i = 0)   // 构造函数,在创建对象时会自动调用,这里同时给参数提供了默认值
        : re(r), im(i)   // 构造函数专有的赋值写法,initialization list
        {}
        complex& operator += (const complex&); // 操作符重载
        double real() const { return re; }  // 成员函数
        double image() const { return im; }
    private:  // 只能在class内部使用
        double re, im;  // 数据放在private部分,这里使用double类型,更好的做法是用模板,在使用的时候由使用者指定类型

        friend complex& __doapl(complex*, const complex&); // friend关键字声明是友元函数,可以直接使用private内的数据或方法
}

// 在类的外部定义的函数为非inline的,但可以通过在前面加上inline关键字来让函数变成inline,但这只是给编译器的一个建议而已,最终是否会是inline由编译器决定
inline complex& __doapl(complex* ths, const complex& r) {
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

额外说明的知识点:

  • 构造函数赋初值要使用initialization list的方式
  • 没有指针的类可以不用写析构函数
  • 构造函数及成员函数都可以被重载,但要注意构造函数不要重复冲突
    比如如下两个构造函数
complex(double r = 0, double i = 0); // 提供了默认值,也可接受无参的情况
complex();
  • 构造函数也可放在private里,常见的场景是单例模式下,demo如下
class A {
  public:
      static A& getInstance();
      setup();
  private:
      A() {
        // do sth
      }
}

inline static A& getInstance() {
  static A a;
  return a;
}

// 如下使用方式
A::getInstance().setup();
  • const 常量成员函数,如果当前函数不会改变数据内容的话,就加上const
  • 函数入参及结果返回,尽量pass by reference,效率更高
  • 相同class的各个object互为友元
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里的数据
  private:
    double re, im;  
}
  • 友元函数打破了封装

对于写一个类会特别关注的几个点

  • 数据一定放在private中
  • 参数尽可能用reference传递,是否加const看情况
  • 返回值也尽量用reference传递
  • 在类的body函数,应该加const的必须加,如果不加,使用者使用的过程中可能报错
  • 要尽量使用构造函数的initialization list赋初值

什么情况下不能return by reference

返回值放在已经存在的变量中时,可返回引用,但如果返回的值是一个新的变量时,就只能return by value,demo如下,对complex类的+操作做操作符重载

inline complex operator + (const complex& l, const complex& r) {
  return complex(l.real() + r.real(), l.image() + r.image());
}

你可能感兴趣的:(GeekBand C++面向对象高级编程(上)第一周笔记)