C++ 之 知识点备忘录(持续更新)

好记性不如烂笔头

本文将记录在学习C++ 过程中的一些知识小点。以便查询和面试准备

const

成员函数后加const

编译器会自动给每一个函数加一个this指针。在一个类的函数后面加上const后,就表明这个函数是不能改变类的成员变量的(加了mutable修饰的除外)。实际上,也就是对这个this指针加上了const修饰

class test
{
public:
  test(int a=10):aa(a){}
  
  ~test(){}
  
  int getA() const 
  { 
  	aa++,
  	bb++;
  	return aa
  }

private:
  int aa;
  mutable int bb;
};

int main()
{
  test t(100);
  int cc = t.getA();  //会报错,因为不能对成员变量aa 进行左值操作
};

protected

经常看见protected类型的成员变量或者接口,为什么会有这个关键字

  • 需求

假如基类Base中有一个成员b,设计要求隐藏这个成员,但是在派生类的成员函数中又经常访问到。如何设计呢?

  • 目的

出于隐藏的目的不能设为公有public,但又需要在派生类的成员函数中经常访问到的基类成员,将它们设置为保护成员,既能起到隐藏的目的,又避免了派生类成员函数要访问它们时只能间接访问所带来的麻烦。

  • 表现形式

保护成员扩大的访问范围表现在:基类的保护成员可以在派生类的成员函数中被访问。

class A{
public:
    A(int x,int y):x(x),y(y){}
protected:
    void print()
    {cout<<"x point:"<<x<<endl<<"y point:"<<y<<endl;}
private:
    int x;
    int y;
};
class B:public A{
public:
    B(int x,int y,int z):A(x,y),z(z){}
    void output()
    {print();cout<<"z point:"<<z<<endl;}//此处调用了基类的protected成员print(),这是合法的。
private:
    int z;
};
int main()
{
    A a(2,3);
    B b(4,5,6);
    //a.print();//这是不合法的,基类对象不能调用保护属性成员
    //b.print();//不合法
    b.output(); //调用public成员,合法;该成员函数内部调用了保护成员print()
    return 0;
}

成员函数指针

class A{                       
public:
 
    void Func(int){            
        std::cout << "I am in A" << std::endl;
    }                          
};

要取得Func函数的指针,必须这么做:

void (A::*pFunc)(int) = &A::Func;

:: 符号, 该符号是一个特殊的操作符,表示pFunc是一个指针,指向类A的成员函数。 获取成员函数的地址不能通过类对象来获取,必须像上面的那样,通过类名来获取,而且要加上取地址操作符(&)

  • 调用方法 1
A a;
(a.*pFunc)(10);
  • 调用方法 2
A *pa = &a;
(pa->*pFunc)(11);

Lamda表达式

[capature list](param list)->return type{ function body};

std::function

std::function和std::bind的使用?

  • 普通函数
#include <iostream>
#include "functional"
using namespace std;

std::function<void(int a)> fun1;
std::function<void(string str)> fun2;
std::function<string(int a, int b)> fun3;

void normal_func(int a)
{
    cout<<"normal function "<<endl;
}

static void normal_static_func(string str)
{
    cout<<"normal static fun:"<<str<<endl;
}

auto lambda = [](int a, int b)->string{
    int c = a+b;
    cout<<"a+b="<<c<<endl;
    return "lambda fun";
};


int main()
{
    cout << "Hello World!" << endl;

    fun1 = normal_func;
    fun1(1);

    fun2 = normal_static_func;
    fun2("2");

    fun3 = lambda;
    cout<<fun3(2,3)<<endl;

    SAY_FUN fp = Person::Say;
    fp();

    system("pause");

    return 0;
}

Hello World!
normal function 
normal static fun:2
a+b=5
lambda fun

  • 类成员静态和非静态函数使用
#include <iostream>
#include "functional"
using namespace std;

class Person{
public:
    void SayHello()
    {
        cout<<"SayHello()"<<endl;
    }

    static void Say()
    {
        cout<<"Say()"<<endl;
    }
};

typedef  std::function<void()> SAY_FUN ;
typedef  std::function<void(Person)> SAY_FUN2;

int main()
{
    cout << "Hello World!" << endl;

    SAY_FUN fp = Person::Say;
    fp();

    Person per;
    //类中的非静态成员函数借助bind的做法
    fp = std::bind(&Person::SayHello, per);
    fp();

    //类中的非静态成员函数不借助bind的做法
    SAY_FUN2 fp2 = &Person::SayHello;
    fp2(per);


    system("pause");

    return 0;
}
  • output
Hello World!
Say()
SayHello()
SayHello()

友元类和有元函数

Friend Classes(友元类)

一个类中的私有成员变量或者函数,在类外是没有办法被访问的。但是,如果我们必须要访问该怎么办呢?这就要用到友元函数或者友元类了。

而友元函数和友元类,就相当于一些受信任的人。我们在原来的类中定义友元函数或者友元类,告诉程序:这些函数可以访问我的私有成员。

C++通过过friend关键字定义友元函数或者友元类。

  • 声明
    friend class aClass;
class CCar
{
private:
    int price;
    friend class CDriver;  //声明 CDriver 为友元类
};

class CDriver
{
public:
    CCar myCar;
    void ModifyCar()  //改装汽车
    {
        myCar.price += 1000;  //因CDriver是CCar的友元类,故此处可以访问其私有成员
    }
};

int main()
{
    return 0;
}
#include <iostream>

using namespace std;

class Date {
public:
    Date (int year, int month, int day) {
        this -> year = year;
        this -> month = month;
        this -> day = day;
    }
    friend void p();

private:
    int year;
    int month;
    int day;
};

void p() {
    Date birthday(2020, 12, 29);
    birthday.year = 2000;
    cout << birthday.year << endl;
}

int main()
{
    p();
    return 0;
}

虚析构函数

为什么需要虚析构函数?简而言之,是为了防止内存泄漏。
那这里的内存泄漏又是怎么产生的呢? 背后的逻辑是什么?

  • 产生内存泄漏的原因:
  1. 派生类的析构函数中有需要回收的内存(这些内存在堆上分配的)
  2. 在编程过程中采用了基类指针指向派生类对象,如为了实现多态,并且通过基类指针将该对象销毁

就会因为基类的析构函数为非虚析构函数而不触发动态绑定,从而没有调用派生类的析构函数而导致内存泄漏。

(C++中基类的析构函数为什么要用virtual虚析构函数)[https://blog.csdn.net/iicy266/article/details/11906457?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&utm_relevant_index=1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值