C++校招八股

news/2024/5/20 21:48:00

c++类的访问权限与继承方式

  1. 公有成员在任何地方都可以被访问,包括类的外部和派生类。
  2. 受保护成员在类的内部和派生类中可以被访问,但在类的外部不可访问。
  3. 私有成员只能在类的内部访问,包括类的成员函数和友元函数,不允许在类的外部或派生类中访问。

#include <iostream>
#include <string>
using namespace std;
class Parent
{// 公有成员在任何地方都可以被访问,包括类的外部和派生类。
public:string name;void info_init(string name,string car,int password){this->name=name;this->car=car;this->password=password;}void print_info(){cout<<"name:"<<name<<endl;cout<<"car:"<<car<<endl;cout<<"password:"<<password<<endl;}// 受保护成员在类的内部和派生类中可以被访问,但在类的外部不可访问。
protected:string car;// 私有成员只能在类的内部访问,包括类的成员函数和友元函数,不允许在类的外部或派生类中访问。
private:int password;
};int main()
{Parent p1;p1.info_init("jay","NIO",10086);p1.print_info();return 0;
}

多态的构成条件

1.必须通过基类的指针或者引用调用虚函数

2.被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。重写的三同(函数名,参数,返回值)

3.派生类可不加virtual

#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:virtual void buy_ticket(){cout << "成人--全价票" << endl;}
};class Child : public Parent
{
public:void buy_ticket(){cout << "儿童--半价票" << endl;}
};void func(Parent &p)
{p.buy_ticket();
}
int main()
{Parent p;Child c;func(p);func(c);return 0;
}

virtual修饰析构函数

虚析构函数可以确保首先调用子类的析构函数, 然后调用父类的析构函数 ;这样可以避免在释放子类对象时出现资源泄漏的情况 ;
当使用父类指针指向一个子类对象时,如果要通过 delete 释放该指针指向的对象,如果是正常的析构函数, 没有使用 virtual 定义虚析构函数 , 则只会调用父类的析构函数, 子类的析构函数不会被调用到 ;

#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:Parent(){cout << "Parent()" << endl;}virtual ~Parent(){cout << "~Parent()" << endl;}
};class Child : public Parent
{
public:Child(){cout << "Child()" << endl;}~Child(){cout << "~Child()" << endl;}
};void func(Parent *p)
{delete p;
}
int main()
{// Parent* p1 = new Parent();Child *p2 = new Child();func(p2);return 0;
}

c++11的override 和 final

  • fianl:修饰虚函数,表示该虚函数不能再被重写
  • 放在类的后面表示该类无法被继承,也就是阻止了从类的继承,放在虚函数后面该虚函数无法被重写,表示阻止虚函数的重载

  • override:检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。

初始化列表 

 初始化列表是一种在构造函数初始化类成员变量的语法。初始化列表在构造函数体执行之前完成成员的初始化。这种方式有时候比在构造函数中使用赋值更高效,并且适用于那些成员变量是常量或者是引用的情况。

初始化列表用法

const成员变量、引用成员变量、没有默认构造函数的自定义类型成员只能在初始化列表初始化

#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:string name;// 使用初始化列表可以确保所有成员变量在构造函数体执行前都已初始化//初始化列表能只能初始化一次,多次初始化会报错:Parent(string name =NULL, int wealth = -1, int password = -1) : name(name), wealth(wealth), password(password){cout << "Name: " << name << '\t' << "wealth: " << wealth << '\t' << "password: " << password << endl;}protected:int wealth;private:int password;
};int main()
{Parent p("jay", 10000, 10086);Parent p1("jj");return 0;
}

友元三种实现方式

友元(friend)是一种机制,允许一个类或者函数访问另一个类的私有成员。通过将其他类或函数声明为友元,可以使它们在访问另一个类的私有成员时绕过访问限制。

  1. 全局函数做友元
  2. 类做友元
  3. 成员函数做友元
#include <iostream>
#include <string>
using namespace std;
class Parent
{friend void globalFunc(Parent *p);//告诉编译器此函数为友元,可以访问类内私有成员public:string name="jay";protected:int wealth = 8848;private:int password = 10086;
};
//全局函数做友元
void globalFunc(Parent *p)
{cout << p->name << endl;cout << p->wealth << endl;cout << p->password << endl;
}
int main()
{Parent p;globalFunc(&p);return 0;
}
#include <iostream>
#include <string>
using namespace std;
class Parent
{friend class GrandParent;//告诉编译器此函数为友元,可以访问类内私有成员public:string name="jay";protected:int wealth = 8848;private:int password = 10086;
};
class GrandParent{
public:void getInfo(Parent *p);
};
//全局函数做友元
void GrandParent::getInfo(Parent *p)
{cout << p->name << endl;cout << p->wealth << endl;cout << p->password << endl;
}
int main()
{Parent p;GrandParent g;g.getInfo(&p);return 0;
}
#include <iostream>
#include <string>
using namespace std;
class GrandParent
{
public:void getInfo();void getInfo1();
};class Parent
{friend void GrandParent::getInfo(); // 告诉编译器此函数为友元,可以访问类内私有成员public:string name = "jay";protected:int wealth = 8848;private:int password = 10086;
};void GrandParent::getInfo()
{Parent*p=new Parent;cout << "getInfo(): " << p->name << "  " << p->wealth << "  " << p->password << endl;
}
void GrandParent::getInfo1()
{Parent*p=new Parent;// 无法访问//cout << "getInfo1(): " << p->name << "  " << p->wealth << "  " << p->password << endl;
}
int main()
{GrandParent g;g.getInfo();return 0;
}

C++几种构造函数

  1. 默认构造
  2. 有参构造
  3. 拷贝构造
  4. 移动构造函数:接受同一类的对象的右值引用作为参数,用于将资源从一个对象转移到另一个对象,通常用于提高效率。
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
public:string data;// 默认构造函数:无参数的构造函数,如果类没有定义任何构造函数,则编译器会自动生成默认构造函数。// 默认构造函数被用于创建对象时,如果没有提供参数,会被调用。MyClass(){this->data = "默认构造函数";cout << "默认构造函数" << endl;}// 参数化构造函数:带有参数的构造函数,用于接受特定参数来初始化对象的成员变量。MyClass(string str) : data(str){cout << "有参数构造函数" << endl;}// 拷贝构造函数:接受同一类的对象作为参数,用于以同一类对象的内容创建新对象。通常用于对象的深拷贝。MyClass(const MyClass &obj) : data(obj.data){cout << "拷贝构造函数" << endl;}~MyClass(){cout<<"-----------------------"<<endl;}
};int main()
{MyClass obj;MyClass obj1("hello");MyClass obj2(obj1);return 0;
}

 指针和引用

  • 指针是一个变量,其值为另一个变量的地址;引用是一个别名,它相当于已经存在变量的另一个名字。
  • 使用指针可以直接访问或修改内存中的数据。
  • 指针可以被重新赋值指向不同的地址,甚至可以指向空值(nullptr);引用必须在定义时初始化,并且一旦初始化后不能再引用其他变量
  • 指针需要解引用操作符 * ;引用可以直接访问原始变量的值,而不需要解引用操作符
  • 指针本身占用内存空间;而引用不占用额外的内存空
#include <iostream>
#include <string>
using namespace std;int main()
{int x = 10;int *p = &x;  // 指针是一个变量,其值为另一个变量的地址int &ref = x; // 引用是一个别名,它相当于已经存在变量的另一个名字;引用必须在定义时初始化,并且一旦初始化后不能再引用其他变量cout << "x=" << x << " *p=" << *p << " ref=" << ref << " p=" << p << endl;x = 20;cout << "x=" << x << " *p=" << *p << " ref=" << ref << " p=" << p << endl;*p = 30;cout << "x=" << x << " *p=" << *p << " ref=" << ref << " p=" << p << endl;ref = 40;cout << "x=" << x << " *p=" << *p << " ref=" << ref << " p=" << p << endl;return 0;
}

new/delete与malloc/free的异同

相同点

  1. 都可用于内存的动态申请和释放

不同点

  1. 前者是C++运算符,后者是C/C++语言标准库函数
  2. new自动计算要分配的空间大小,malloc需要手工计算
  3. new是类型安全的,返回完整的类型;malloc不是。
  4. new调用名为operator new的标准库函数分配足够空间并调用相关对象的构造函数,delete对指针所指对象运行适当的析构函数;然后通过调用名为operator delete的标准库函数释放该对象所用内存。后者均没有相关调用
  5. 后者需要库文件支持,前者不用;new是封装了malloc,直接free不会报错,但是这只是释放内存,而不会析构对象

解释每个示例的含义

//声明了一个数组 p,数组中包含 10 个指向 int 类型的指针
int *p[10];
//一个指针 p,它指向一个包含 10 个 int 类型元素的数组。
int (*p)[10];
//声明了一个函数 p,该函数接受一个 int 类型的参数,并返回一个 int 类型的指针。
int *p(int);
//声明了一个指针 p,它指向一个函数,该函数接受一个 int 类型的参数,并返回一个 int 类型的值
int (*p)(int);

static在类中的作用

静态成员变量 

  1. static + 类型+变量名后,那么该类 不论 创建了多少个 实例对象 , 这些对象都会共享 该 static " 静态成员变量 " ;
  2. 成员变量一旦加了static关键字后就会处在静态区的,类是处在栈区的, 所以静态的成员变量只能在类外去定义,类内只能是声明,而且不可赋值!!!
  3. 静态成员变量 的 生命周期 就是 程序的声明周期 ;静态成员变量在 应用启动时 初始化 , 在 进程结束时销毁 ;

静态成员变函数 

  1. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  2. 静态成员也是类的成员,受public、protected、private 访问限定符的限制
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:Person(){this->var++;this->s_var++;cout << "Person(): var=" << this->var <<" s_var="<<this->s_var<<" constVar=" <<this->constVar<<endl;}~Person(){this->var--;this->s_var--;cout << "~Person(): var=" << this->var <<" s_var="<<this->s_var<<" constVar=" <<this->constVar<<endl;}static int s_var; // 必须在类内定义,类外初始化,static int s_var=0会报错int var=0;//非静态变量可以类内声明并定义.但是不可外部定义const int constVar=0;static void staticFinc(){cout << s_var << endl;//静态成员函数没有隐藏的this指针,不能访问任何非静态成员//cout << var << endl;}};
int Person::s_var = 0; // 在类外部初始化静态成员变量
//int Person::var = 0; // 不可在类外部初始化非静态成员变量
//int Person::constVar=100;
int main()
{Person p;Person p1;return 0;
}

C++ class与struct区别

相同点

  1. 两者都拥有成员函数、公有和私有部分
  2. 任何可以使用class完成的工作,同样可以使用struct完成

不同点

  1. 两者中如果不对成员不指定公私有,struct默认是公有的,class则默认是私有的
  2. class默认是private继承,而struct默认是public继承
#include <iostream>
#include <string>
using namespace std;
struct Person
{Person(){this->name="NULL";this->age=-1;this->password=-1;cout << "Person()" << endl;}~Person(){cout << "~Person()" << endl;}void print_info(){cout<<"name:"<<name<<" age:"<<age<<" password:"<<password<<endl;}string name;protected:int age;private:int password;
};
struct Student:Person {Student(){cout << "Student()" << endl;}~Student(){cout << "~Student()" << endl;}};
int main()
{Person p;Student s;p.name="person";//struct默认是public继承,因此可以访问公有成员s.name="student";p.print_info();s.print_info();return 0;
}

C++的顶层const和底层const

概念区分

  • 顶层const:指的是const修饰的变量本身是一个常量,无法修改,指的是指针,就是*号的右边
  • 底层const:指的是const修饰的变量所指向的对象是一个常量,指的是所指变量,就是*号的左边 
int a = 10;int* const b1 = &a;        //顶层const,b1本身是一个常量
const int* b2 = &a;       //底层const,b2本身可变,所指的对象是常量
const int b3 = 20; 		   //顶层const,b3是常量不可变
const int* const b4 = &a;  //前一个const为底层,后一个为顶层,b4不可变
const int& b5 = a;		   //用于声明引用变量,都是底层const

拷贝初始化和直接初始化

在 C++ 中,初始化对象的方式可以分为两种:拷贝初始化(copy initialization)和直接初始化(direct initialization)。

1. 拷贝初始化(Copy Initialization):

  •    使用等号=进行初始化的方式称为拷贝初始化。
  • 在拷贝初始化中,编译器会尝试使用构造函数将右侧的值转换为左侧的类型,并将结果拷贝到左侧的对象中。这种初始化方式适用于将一个对象的值拷贝给另一个对象,或者通过一个值来初始化一个新的对象。

2. 直接初始化(Direct Initialization):

  • 在初始化过程中直接使用圆括号()进行初始化的方式称为直接初始化。
  • 在直接初始化中,编译器会选择合适的构造函数来初始化对象,而不需要进行额外的拷贝操作。

静态类型,动态类型;静态绑定,动态绑定

对C++中的静态类型,动态类型,静态绑定,动态绑定的理解_静态类型和动态类型,静态绑定和动态绑定-CSDN博客

  1. 静态类型变量声明时候的类型,在编译阶段就可以确定了
  2. 动态类型指针或者引用所代表的内存中的对象的类型,在运行阶段才可以确定
  3. 静态绑定:有人也叫为早绑定,早绑定什么呢?对象所调用的函数的地址,这个阶段是程序编译阶段就确定的了;
  4. 动态绑定:有人也叫晚绑定,也就是编译阶段时候不能确定对象调用函数的地址,需要程序运行到调用函数的阶段才可以确定;

智能指针的原理、常用的智能指针及实现

原理

  • C++ 智能指针底层是采用引用计数的方式实现的。简单的理解,智能指针在申请堆内存空间的同时,会为其配备一个整形值(初始值为 1),每当有新对象使用此堆内存时,该整形值 +1;反之,每当使用此堆内存的对象被释放时,该整形值减 1。当堆空间对应的整形值为 0 时,即表明不再有对象使用它,该堆空间就会被释放掉。

常用的智能指针
(1)shared_ptr
实现原理:采用引用计数器的方法,允许多个智能指针指向同一个对象,每当多一个指针指向该对象时,指向该对象的所有智能指针内部的引用计数加1,每当减少一个智能指针指向对象时,引用计数会减1,当计数为0的时候会自动的释放动态分配的资源。
 

template<typename T>
class SharedPtr
{
public:SharedPtr(T* ptr = NULL):_ptr(ptr), _pcount(new int(1)){}SharedPtr(const SharedPtr& s):_ptr(s._ptr), _pcount(s._pcount){(*_pcount)++;}SharedPtr<T>& operator=(const SharedPtr& s){if (this != &s){if (--(*(this->_pcount)) == 0){delete this->_ptr;delete this->_pcount;}_ptr = s._ptr;_pcount = s._pcount;(*_pcount)++;}return *this;}T& operator*(){return *(this->_ptr);}T* operator->(){return this->_ptr;}~SharedPtr(){--(*(this->_pcount));if (*(this->_pcount) == 0){delete _ptr;_ptr = NULL;delete _pcount;_pcount = NULL;}}
private:T* _ptr;int* _pcount;//指向引用计数的指针
};

运算符重载

成员函数重载

#include <iostream>
#include <string>
using namespace std;class Person
{
public:int _age=10;int _money=10;//成员函数重载Person operator+(Person&p){Person tmp;tmp._age=this->_age+p._age;tmp._money=this->_money+p._money;return tmp;}
};int main()
{Person p1,p2,p3;p3=p1+p2;//成员函数重载本质 p3=p1.operator+(p2)cout<<p3._age<<" "<<p3._money<<endl;//20 20return 0;
}

全局函数重载

#include <iostream>
#include <string>
using namespace std;class Person
{
public:int _age = 10;int _money = 10;
};// 全局函数重载
Person operator+(Person &p1, Person &p2)
{Person tmp;tmp._age = p1._age + p2._age;tmp._money = p1._money + p2._money;return tmp;
}
int main()
{Person p1, p2, p3;p3 = p1 + p2;								 // 全局函数重载本质 p3=operator+(p1,p2)cout << p3._age << " " << p3._money << endl; // 20 20return 0;
}


http://www.mrgr.cn/p/66005618

相关文章

大数据面试题 —— 数据仓库

目录 数据仓库是什么数据仓库和数据库的区别为什么要对数据仓库分层数仓分层&#xff0c;以及每一层的作用维度建模的三种模型范式建模、维度建模维度建模过程&#xff0c;如何确定这些维度 ***维度模型的各个维度之间是怎么聚合的聚合过程的数据倾斜怎么解决&#xff1f;数据质…

【FX110】2024外汇市场中交易量最大的货币对是哪个?

作为最大、最流动的金融市场之一&#xff0c;外汇市场每天的交易量高达几万亿美元&#xff0c;涉及到数百种货币。不同货币对的交易活跃程度并不一样&#xff0c;交易者需要根据货币对各自的特点去进行交易。 全年外汇市场中涉及美元的外汇交易超过50%&#xff01; 实际上&…

基于Vue3与ElementUI Plus的酷企秀场景可视化DIY设计器:前端技术引领下的数字化展示新篇章

一、引言 在当今信息化高速发展的时代&#xff0c;企业对于展示自身形象、提升用户体验以及增强品牌知名度的需求日益迫切。针对这一市场需求&#xff0c;我们推出了基于Vue3与ElementUI Plus的酷企秀场景可视化DIY设计器。该产品不仅具备电子画册、VR全景、地图秀三大核心功能…

MATLAB 三维空间中在两点之间等间隔插入多个点 (67)

MATLAB 三维空间中在两点之间等间隔插入多个点 (67) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 用于加密直线点云,具体为根据给定的直线端点,沿着该直线方向,插入多个点,从而加密。具体方法和效果如下所示: 二、算法实现 1.代码 代码如下(示例): % 定…

【Qt QML】Frame组件

Frame&#xff08;框架&#xff09;包含在&#xff1a; import QtQuick.Controls继承自Pane控件。用于在可视框架内布局一组逻辑控件。简单来说就是用来包裹和突出显示其他可视元素。Frame不提供自己的布局&#xff0c;但需要自己对元素位置进行设置和定位&#xff0c;例如通过…

C语言leetcode刷题笔记2

C语言leetcode刷题笔记2 第4题&#xff1a;283.移动零互换直接移动 第5题&#xff1a;122.买卖股票的最佳时机‖递归&#xff08;超时&#xff09;动态规划贪心算法 第6题&#xff1a;49.字母异位词分组优化 第4题&#xff1a;283.移动零 给定一个数组 nums&#xff0c;编写一…

艾体宝方案 | 加密USB金融解决方案

在现代金融行业中&#xff0c;保护敏感数据和合规性已成为至关重要的任务。为了帮助金融公司应对移动性风险和合规挑战&#xff0c;我们提供了一种高效的加密USB解决方案。 一、为什么金融公司需要加密USB解决方案 1、降低移动性风险 金融服务公司正在迅速过渡到一种模式&a…

智慧旅游引领未来风尚,科技助力旅行更精彩:科技的力量推动旅游业创新发展,为旅行者带来更加便捷、高效和智能的旅行服务

目录 一、引言 二、智慧旅游的概念与特点 &#xff08;一&#xff09;智慧旅游的概念 &#xff08;二&#xff09;智慧旅游的特点 三、科技推动旅游业创新发展 &#xff08;一&#xff09;大数据技术的应用 &#xff08;二&#xff09;人工智能技术的应用 &#xff08;…

Vue从入门到实战Day03

一、生命周期 1. 生命周期四个阶段 思考&#xff1a; ①什么时候可以发送初始化渲染请求&#xff1f; 答&#xff1a;越早越好&#xff0c;在创建阶段后 ②什么时候可以开始操作DOM&#xff1f; 答&#xff1a;至少DOM得渲染出来&#xff0c;在挂载阶段结束后。 Vue生命周…

API低代码平台介绍2-最基本的数据查询功能

最基本的数据查询功能 本篇文章我们将介绍如何使用ADI平台定义一个基本的数据查询接口。由于是介绍平台具体功能的第一篇文章&#xff0c;里面会涉及比较多的概念介绍&#xff0c;了解了这些概念有助于您阅读后续的文章。 ADI平台的首页面如下&#xff1a; 1.菜单介绍 1.1 O…

C++ 动态内存管理

例如&#xff1a;动态内存和释放单个数据的存储区 一 用new运算符初始化单个数据的存储区 举例

Linux-信号执行

1. 信号什么时候被处理 当进程从内核态返回到用户态的时候&#xff0c;进行信号的检测和处理 什么内核态&#xff0c;什么又是用户态呢&#xff1f; 当进程在CPU上运行时&#xff0c;内核态&#xff1a;允许进程访问操作系统的代码和数据&#xff0c;用户态&#xff1a;进程只…

计算机网络chapter1——家庭作业

文章目录 复习题1.1节&#xff08;1&#xff09; “主机”和“端系统”之间有何不同&#xff1f;列举几种不同类型的端系统。web服务器是一种端系统吗&#xff1f;&#xff08;2&#xff09;协议一词常用来用来描述外交关系&#xff0c;维基百科是如何描述外交关系的&#xff1…

iOS 17 / iPad OS 17屏蔽更新

iOS 17 / iPad OS 17屏蔽更新 1&#xff0c;进入屏蔽iOS更新的描述文件下载链接 下载链接 wx 搜索 Geek 前端发送屏蔽更新进行获取 2&#xff0c;复制这段链接&#xff0c;在Safari浏览器中打开&#xff0c;注意打开后别点击下载&#xff01;要先改时间&#xff01; 3&#…

K8s必须掌握的7个调试技巧

K8s必须掌握的7个调试技巧 原创 艾叔编程 艾叔编程 2024-05-09 09:35 北京 听全文Kubernetes(K8s)调试技术是指在使用Kubernetes集群过程中,用于定位和解决问题的方法和技术。Kubernetes是一个复杂的系统,它负责管理容器化的应用程序,确保它们按照预期运行。当应用程序出现…

【数据结构】之栈的应用——有效的括号

文章目录 有效的括号 有效的括号 原题链接&#xff1a;有效的括号 详解栈的链接 这道题可以利用栈来解决 1.左括号入栈 2.右括号与出栈顶左括号匹配 //创建一个动态的栈 typedef char STDateType; typedef struct Stack {STDateType* a;//储存指定数据类型的数组int top…

安防视频/视频汇聚系统EasyCVR视频融合云平台助力智能化酒店安防体系的搭建

一、背景需求 2024年“五一”假期&#xff0c;全国文化和旅游市场总体平稳有序。文化和旅游部6日发布数据显示&#xff0c;据文化和旅游部数据中心测算&#xff0c;全国国内旅游出游合计2.95亿人次。“五一”假期县域市场酒店预订订单同比增长68%&#xff0c;而酒店作为一个高…

最新:Lodash 严重安全漏洞背后你不得不知道的 JavaScript 知识

可能有信息敏感的同学已经了解到&#xff1a;Lodash 库爆出严重安全漏洞&#xff0c;波及 400万 项目。这个漏洞使得 lodash “连夜”发版以解决潜在问题&#xff0c;并强烈建议开发者升级版本。 我们在忙着“看热闹”或者“”升级版本”的同时&#xff0c;静下心来想&#xf…

震惊,现在面试都加科技与狠货了

震惊&#xff0c;现在面试都加科技与狠货了 生成式AI盛行的现在&#xff0c;程序员找工作变容易了吗我和老痒喝着大酒&#xff0c;吃着他的高升宴&#xff0c;听他说他面试的各种细节&#xff0c;老狗我只恨自己动作慢了一步&#xff0c;不然现在在那侃侃而谈的就是我了。 面试…

电商核心技术揭秘53:社群营销的策略与实施

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商技术揭秘四十一&#xff1a;电商平台的营销系统浅析 电商技术揭秘四十二&#…