C++复习笔记

C++研究笔记


工程化

A.h

成员函数1;
成员函数2;


A.c

#include"A.h"

A::成员函数1{}
A::成员函数2{}

demo.c

#include"A.h"

int main()
{
  todo...
}

相比于C,C++的新特性

  • C++有布尔类型,C没有哦…

初始化方法

  1. 复制初始化 int x = 1024; (C语言有的特性)
  2. 直接初始化 int x(1024);

随用随定义

  1. C语言:所有变量定义必须位于函数体的前面
  2. 随用随定义

输入输出方式

C

C++

  • 不用关心占位符 ;譬如 %d ,%f …
  • 不用关心数据类型

    cout << oct|dec|hex|boolalpha << x <

OOP

数据的封装

class Student
{
  public:
    void setAge(int _age){age = _age;}
    int getAge(){return age;}
  private:
    string name;
    int age;
}
  • 可以设置只读属性,类的封装不设置对外写接口

内联函数

  • 类内定义的函数优先选择编译为内联函数

内联函数

类外定义

  1. 同文件 类外定义 类名::成员{}
  2. 分文件类外定义 文件名 类名.h 调用者: #include”类名.h” 类名::成员{}

构造函数

  • 构造函数在对象实例化时被自动调用,且仅调用一次
  • 构造函数与类同名
  • 构造函数没有返回值
  • 构造函数可以有多个重载形式
  • 实例化对象时仅用到一个构造函数
  • 当用户没有定义构造函数时,编译器自动生成一个构造函数

初始化列表

student():m_strName("rose"),m_iAge(20){}
  • 初始化列表先于构造函数执行
  • 初始化列表只能用于构造函数

侯捷老师提到过推荐使用初始化列表

  • 初始化列表可以征服const声明的常量,个人感觉就像先执行初始化列表,进行变量m_Age的初始化,然后const修饰将变量转换成常量

    person(int age):m_Age(age){}

    private:
    const int m_Age;

拷贝构造函数

定义

类名(const 类名 &变量名)
  • 没有定义拷贝构造函数,系统会自动生成一个默认的拷贝构造函数
  • 直接初始化,复制初始化,系统自动调用拷贝构造函数

整个对象的拷贝

析构函数

~类名(){}

对象数组

Coordinage coor[3] //栈实例化对象数组
coor[0].m_iX  //访问成员

Coordinate *p = new Coordinate[3];  //堆实例化对象数组
p[0].m_iX  // p->m_iX 

p++;

P->m_iX;   // 第二个单元

深拷贝与浅拷贝

浅拷贝

*两个实例化对象指向同一块内存,最后操作的对象总是覆盖掉前一对象的操作;释放内存时,能够导致内存的二次释放

深拷贝

  1. 重新申请内存
  2. 传入对象的内存赋值给新申请的内存,通常用遍历的方式来赋值

Test(const Test& arr){

    m_pArr = new int[m_iCount];
    for(int i=0;i<m_iCount;i++)
    {
      m_pArr[i] = arr.m_pArr[i];
    }

}

对象指针

Coordinate *p = new Coordinate;

p->member;
(*p).member; //这个最是让自己匪夷所思的,p指向了Obj,*p的意思就是读取了Obj

#include <iostream>
using namespace std;
class Coordinate
{

public:
    Coordinate()
    {
    }
    // 打印坐标的函数
    void printInfo()  
    {
        cout<<"("<<m_iX<<","<<m_iY<<")"<<endl;
    }
public:
    int m_iX;
    int m_iY;
};
int main(void)
{
    //定义对象数组
    Coordinate *coorArr = new Coordinate[2];
    coorArr[0].m_iX = 1;
    coorArr[0].m_iY = 2;
    coorArr[1].m_iX = 3;
    coorArr[1].m_iY = 4;


    //遍历数组,打印对象信息
    for(int i = 0; i < 2; i++)
    {
        coorArr[i].printInfo();
    }   
    return 0;
}
  • 指针访问对象数组成员:指针名[偏移量].成员

测试
1. &coorArr[0] 打印出来的结果是地址,coorArr[0]是一个数值嘛?
2. 测试结果,error,姑且就把它当作对象看待


对象成员指针

class Line
{
public:
    Line();
    ~Line();
private:
    Coordinate *m_pCoorA;
    Coordinate *m_pCoorB;
}

Line::Line()
{
    m_pCoorA = new Coordinate(1,3);
    m_pCoorB = new Coordinate(5,6);

}

Line::~Line()
{
    delete m_pCoorA;
    delete m_pCoorB;
}

对象成员指针

this指针

  • 解决参数与数据成员同名
  • this指针在参数列表中的位置

    return (*this) //返回一个对象

  • 返回引用对象,比如第一次操作改变了成员变量,第二次操作 返回对象.成员变量,变量会发生改变

  • 如果直接返回一个对象,第二次操作不会改变变量

this指针的特殊用法


#include<iostream>
using namespace std;

class Array
{
    public:
    Array(int len):m_len(len)
    {
        cout<<"构造函数"<<endl;
    }

    void set(int len)
    {
        m_len = len;
    }

    int get()
    {
        return m_len;
    }

    Array printinfo()
    {
        cout<<"m_len= "<<m_len<<endl;
        return (*this);
    }

    private:
    int m_len;
};

测试程序1

int main()
{
        Array arr1(10);
        arr1.printinfo().set(5);
        cout<<arr1.get()<<endl;
        return 0;
}
  • 测试结果arr1的数值没有发生改变,因为返回的另外一个对象,该对象为临时对象

解决方法

Array& printinfo()
{
    cout<<"m_len= "<<m_len<<endl;
    return (*this);
}
  • 将返回对象修改为返回引用,指向同一个内存区域,就可以测试成功

返回对象修改为对象指针

Array* printinfo()
{
    cout<<"m_len= "<<m_len<<endl;
    return this;
}

int main()
{
        Array arr1(10);
        arr1.printinfo()->set(5);
        cout<<arr1.get()<<endl;
        return 0;
}

const

  1. const int * p = int const *p

const修饰的是(*p) , 即指针指向的数值,数值为常量

  1. int * const p

const修饰的是p, 指针为常量

  1. int x=3 const int &y = x x=0正确,y=20错误(const修饰了引用y,y为常量,不可以赋值)

  2. int x =3 (变量) const int x= 3 (常量)

    • 如果成员变量前const修饰,那么构造函数在函数体内定义,这样的方法会产生error;但是倘若使用初始化列表的方法的话,程序会成功,初始化列表完成了成员变量的初始化,然后const修饰,之后成员变量为常量,不可进行赋值操作了.
    • 常对象成员,也可以用初始化列表这样的技术手段

常成员函数

函数 const;

  • 常成员函数中不能改变成员变量的数值

    void change() const
    {
    m_iX = 10;
    }

    void change(const *this)
    {
    this->m_iX = 10; //error const修饰了(*p)指向的数值,数值为常量
    }

    //互为重载
    void changeX() const;
    void changeX();

  • 调用的时候需要前面const来区分,否则调用普通函数,而不是常成员函数

  • 常成员函数的本质是内部使用常this指针
  • 常成员函数内不能调用普通的成员函数

常指针与常引用

int main(void)
{
    Coordinate coor1(3,5);
    const Coordinate &coor2 = coor1;
    const Coordinate *pCoor3 = &coor1;

    coor1.printInfo();
    coor2.getX();  //error getX()要求传入读写权限的参数,而coor2传入的this指针只有读权限   
    pCoor3->getY(); //error ...同上
    return 0;
}
  • getX, getY为普通成员函数,有着读写权限.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值