C++知识总结

大端小端

对于0x0110
大端(大端放在低地址):0x01放在低地址
小端(小端放在低地址):0x10放在低地址

NULL与nullptr

NULL: 也就是0,可以赋值给int;int a = NULL;
nullptr: 该关键字只能赋值给指针 int *p= nullptr;

实例化对象

// 栈中实例化对象,内存自动释放,调用方式:.
Worker worker; 

// 堆中实例化对象,内存需手动释放,调用方式:->
Worker *p = new Worker();
delete p;
p = NULL;

构造函数与析构函数

构造函数:在对象实例化时被调用,无返回值。函数名与类名相同,可以是有参数的函数
析构函数:在对象销毁的时候调用
赋值构造函数:也叫拷贝构造函数
类型转换构造函数:只有一个参数,实现类型的自动转换

class Complex {
    public:
        double real, imag;
        Complex(int i) {};
        Complex(double r, double i) {
            real = r;
            imag = i;
        }
};

Complex::Complex(int i) { // 类型转换构造函数
    cout << "intConstructor called" << endl;
    real = i;
    imag = 0;
}

int main() {
    Complex c1(7, 8);   // 初始化构造函数,直接构造
    Complex c2 = 12;    // 调用类型转换构造函数
    c1 = 9;             // 调用类型转换构造函数,9被自动转换为一个临时对象
    return 0;
}

// relsut:
intConstructor called
intConstructor called

父类子类数据访问

  • 父类数据访问
    对象实例禁止访问类中的private和protected的数据成员
    类内可以访问
  • 子类数据访问
    子类可以访问父类中的protected成员
    子类禁止访问父类中的private成员

this指针

从C++程序到C程序的翻译,可以知道,C只有全局的函数,要使得某个成员函数与类关联起来,需要this
重要:在非静态函数中,this指针是指向函数作用对象的指针

class Complex {
    public:
        double real, imag;
        Complex(double r, double i):real(r),imag(i){}
        void Print() {
            cout << "real:" << real << ",  imag:" << imag << endl;
        }
        Complex AddOne(){
            this->real++;
            return *this;
        }
};

int main() {
    Complex c1(7, 8);
    c1.Print();
    c1.AddOne();
    c1.Print();
    return 0;
}

// result:
real:7,  imag:8
real:8,  imag:8

指针与引用

  • 指针
    指针常量:不能再指向别地址
    常量指针:指向常量的指针,指向的内容不能通过指针进行修改
    指针数组:存放指针的数组
    数组指针:指向数组的指针
// 指针常量
int a = 3; int b = 4;
int *const p = &a; 
p = &b;  // 错误, p不能再更改;

// 常量指针
int a = 3;
const int *p = &a; 
*p = 40;  // 出错, 不能编译
a = 40;  // 这样可以

// 指针数组
int *Arr[10];  // 变量名arr先与[]组合是数组
// 数组指针
int (*p)[10];  // 变量名p先与*组合是指针

// 指针指向数组
int arr[] = {1, 2, 3, 4};
int * p = arr;
*(p + 2) => arr[2];  // 通过指针访问元素
  • 引用
    引用(变量的别名)必须初始化:要有实际的变量名。int &b = a;a是变量名

const

作用:

  • 修饰变量;该变量不可以改变,该变量需要进行初始化const int a = 0;
  • 修饰指针;前置条件int a = 0; int b = 1;
指向常量的指针指针常量
const int *p = &a;int * const p = &a;
*p = 80;修改指向的常量会报错p = &b;修改指针的指向会报错
  • 修饰函数参数;可以将非const的实参传给const修饰的参数,只需要保持函数内不变即可
  • 修饰成员函数
    • const修饰的成员函数内部不能修改任何成员变量
    • const修饰的成员函数不能调用非const成员函数
// const的使用

// 类
class A
{
private:
    const int a;                // 常对象成员,只能在初始化列表赋值

public:
    // 构造函数
    A() : a(0) { };
    A(int x) : a(x) { };        // 初始化列表

    // const可用于对重载函数的区分
    int getValue();             // 普通成员函数
    int getValue() const;       // 常成员函数,不得修改类中的任何数据成员的值
};

void function()
{
    // 对象
    A b;                        // 普通对象,可以调用全部成员函数、更新常成员变量
    const A a;                  // 常对象,只能调用常成员函数
    const A *p = &a;            // 指针变量,指向常对象
    const A &q = a;             // 指向常对象的引用

    // 指针
    char greeting[] = "Hello";
    char* p1 = greeting;                // 指针变量,指向字符数组变量
    const char* p2 = greeting;          // 指针变量,指向字符数组常量
    char* const p3 = greeting;          // 自身是常量的指针,指向字符数组变量
    const char* const p4 = greeting;    // 自身是常量的指针,指向字符数组常量
}

// 函数
void function1(const int Var);           // 传递过来的参数在函数内不可变
void function2(const char* Var);         // 参数指针所指内容为常量
void function3(char* const Var);         // 参数指针为常量
void function4(const int& Var);          // 引用参数在函数内为常量

// 函数返回值
const int function5();      // 返回一个常数
const int* function6();     // 返回一个指向常量的指针变量,使用:const int *p = function6();
int* const function7();     // 返回一个指向变量的常指针(自身是常量的指针),使用:int* const p = function7();

重载与重写

重载:函数名相同,参数不同;没有继承关系

  • void func();
  • void func(int a);

重写:对虚函数重写;有继承关系

运算符重载

解决的问题:利用+、-等运算符对类的对象进行计算,否则需要操作成员函数进行计算

class Dollar {
    public:
        int yuan = 0;
        int cent = 0;
        Dollar operator + (const Dollar & dollar);
        Dollar(int _yuan, int cent);
};

Dollar Dollar::operator+(const Dollar &dollar)
{
    Dollar dollarRes(0, 0);
    int c = dollar.cent + cent;
    dollarRes.cent = c % 100;
    int d = dollar.yuan + yuan;
    dollarRes.yuan = d + c / 100;

    return dollarRes;
}

Dollar::Dollar(int _yuan, int _cent) {
    yuan = _yuan;
    cent = _cent;
}

int main()
{
    Dollar dol(10, 5);
    Dollar dol1(10, 95);
    Dollar dor = dol + dol1;
    printf("yuan:%d, cent:%d\n", dor.yuan, dor.cent);
}

// result:
yuan:21, cent:0

封装

  • 初始化列表
    • 初始化列表先于构造函数执行
    • 初始化列表只能用于构造函数
    • 初始化列表可以同时初始化多个数据成员
class Coordinate{
public:
    Coordinate(int x, int y);
private:
    const int m_iX;
    const int m_iY;
};

// 在进行Coordinate方法实现的时候,由于private中的const
// 直接使用会出错Error
Coordinate::Coordinate(int x, int y){
    m_iX = x;
    m_iY = y;
}

// 这里要进行正确的实现
// 需要使用初始化列表
Coordinate::Coordinate(int x, int y):m_iX(x), m_iY(y){}

继承

视频讲解(保护继承与私有继承)

class Person{
public:
        void eat();
        string m_strName;
        int m_iAge;
};
// 公有继承
class Woker:public Person
{
public:
        // void eat();  // 基类已经包含,可以不写
        void work();
        // string m_strName;  // 基类已经包含,可以不写
        // int m_iAge;  // 基类已经包含,可以不写
        int m_iSalary;
};

// 使用
int main(void){
        Worker worker;
        worker.m_strName = "Merry";
        worker.eat();
        return 0;
};
  • 共有继承、保护继承、私有继承在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  • 多重继承、多继承、虚继承
    多重继承:
    在这里插入图片描述
    在这里插入图片描述
    多继承:
    在这里插入图片描述
    在这里插入图片描述
    虚继承:用于解决菱形继承问题
    在这里插入图片描述
// 虚继承
// 用于解决菱形继承问题
class Worker:virtual public Person
{
};

class Farmer:virtual public Person
{
};

class MigrantWorker:public Workerpublic Farmer
{
};

多态

静态绑定:编译时的多态,由函数重载来实现
动态绑定:运行时的多态,由虚函数来实现(virtual关键字
多态具体到语法中是指,使用父类指针指向子类对象,并可以通过该指针调用子类的方法
原理:虚函数表,定义了虚函数的类含有虚函数表,类对象有虚函数表指针,指向虚函数表。子类继承后,首先会继承虚函数表,如果子类进行重写后,使用重写后函数的地址来覆盖原地址
在这里插入图片描述

虚析构函数:为了避免使用父类指针释放子类对象时造成内存泄露。

// 虚析构函数的使用
class Shape
{
public:
    Shape();                    // 构造函数不能是虚函数
    virtual double calcArea();
    virtual ~Shape();           // 虚析构函数
};
class Circle : public Shape     // 圆形类
{
public:
    virtual double calcArea();
    ...
};
int main()
{
    Shape *shape1 = new Circle(4.0);
    shape1->calcArea();    
    delete shape1;  // 因为Shape有虚析构函数,所以delete释放内存时
                    // 先调用子类析构函数,再调用基类析构函数
                    // 防止内存泄漏。
    shape1 = NULL;
    return 0}

虚函数/纯虚函数和抽象类/接口类

  • 虚函数
    • 含有virtual关键字,没有 = 0;函数声明可以有函数定义也可以没有函数定义
    • virtual double calcArea() { return 0; }
  • 纯虚函数
    • 只有函数声明,没有函数定义的虚函数
    • virtual double calcPerimeter() = 0;
  • 抽象类
    • 含有纯虚函数的类
    • 抽象类无法实例化对象
    • 抽象类的子类也可以是抽象类
      • 子类没有对纯虚函数进行实现
      • 子类中含有新的纯虚函数
  • 接口类:更多的表达是一种协议或者能力
    • 只有纯虚函数的类
    • 类中无数据成员、只有成员函数(成员函数都是纯虚函数)

dynamic_cast

  • 只能应用于指针和引用的转换
  • 要转换的类型中必须包含虚函数
  • 转换成功返回子类的地址,失败返回NULL

友元函数

定义在类外部,但有权访问类的所有私有成员与保护成员

#include <iostream>
using namespace std;
 
class Box
{
   double width;
public:
   void setWidth(double wid);
   friend void printWidth(Box box);
};
 
// 成员函数定义
void Box::setWidth(double wid)
{
    width = wid;
} 
// 请注意:printWidth() 不是任何类的成员函数
void printWidth(Box box)
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}
 
// 程序的主函数
int main( )
{
   Box box;
   box.setWidth(10.0);  // 使用成员函数设置宽度
   printWidth(box);  // 使用友元函数输出宽度
   return 0;
}

智能指针

  • unique_ptr:通过封装指针为栈对象(栈对象生命结束后,自动释放),不能被多个实例共享内存
    • std::uniqie_ptr<A> p1(new A());
  • shared_ptr:多个指针可通过计数的方式共享.
    • std::shared_ptr<A> p1 = std::make_shared<A>();
    • std::shared_ptr<A> p2 = p1
  • weak_ptr:当存在循环引用的时,shared_ptr无法释放,会造成死锁
    • std::weak_ptr<A> a;

内存

内存内容的拷贝

lock_guard和unique_lock

多线程lock_guard和unique_lock

内置宏

__LINE__ 		# 代码所在行号
__FUNCTION__	# 代码所在函数
__FILE__		# 代码所在文件 

(long)getpid()	# 获取进程号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值