C++校招八股

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. 动态绑定:有人也叫晚绑定,也就是编译阶段时候不能确定对象调用函数的地址,需要程序运行到调用函数的阶段才可以确定;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/591894.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL45讲(一)(45)

如果使用的是unsigned int 做的主键&#xff0c;如果你用完了&#xff0c;在insert直接就是报冲突的错误 碰到这种情况&#xff0c;只能进行修改字段的属性了&#xff0c;把他换成big unsigned 了&#xff0c;所以建表对字段定义的时候就需要判断好&#xff0c;是否会超过 对于…

我的创作纪念日—128天的坚持|分享|成长

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&am…

H3C MSTP 实验

H3C MSTP 实验 实验拓扑 ​​ 实验需求 所有交换机上创建 Vlan10&#xff0c;Vlan20&#xff0c;Vlan30 和 Vlan40所有交换机之间的端口配置为 Trunk&#xff0c;并放行相关 VLAN按照图示分区域配置 MSTP&#xff0c;并配置主备根网桥 实验步骤 VLAN基础配置&#xff08;…

RateLimiter 限流 —— 通过切面对单个用户进行限流和黑名单处理

关于登录的安全性管理有较多的手段&#xff0c;包括&#xff1b;设备信息、IP信息、绑定的信息、验证码登各类方式。不过在一些网页版的登录中&#xff0c;如果有人想办法把你的验证码给我&#xff0c;我就可以登录你的账户&#xff0c;查看你的数据。对于一些不法分子通过让你…

windows 驱动开发-DMA技术(二)

前面描述了DMA技术中适配器相关的部分以及DMA的分类&#xff0c;接下来看一下系统具体在支持两种DMA时候的操作的细微差别。 此处解释一下Scatter/Gather&#xff0c;这个也翻译为散点/收集&#xff0c;是指指示设备能够读取或写入内存中的任何区域&#xff0c;而不仅仅是特定…

构建智能化商旅服务:酒店中台云服务架构设计与实践

随着商旅行业的不断发展和智能化趋势的兴起&#xff0c;酒店中台云服务成为了提升服务质量和效率的关键。本文将探讨酒店商旅中台云服务的架构设计与实现&#xff0c;介绍其关键特点和最佳实践&#xff0c;助力商旅行业迈向智能化未来。 1. **需求分析与场景设计&#xff1a;*…

【阿里云服务器】ubuntu 22.04.1安装docker以及部署java环境

我的服务器配置是2GB CPU 2GB 内存 Ubuntu22.04 目录 一、阿里云 ubuntu 22.04.1安装docker 二、docker基础命令 三、Windows电脑访问云服务器 四、安装java环境 安装OpenJDK 8&#xff08;可以根据需要安装其他版本的JDK&#xff09; 安装java的依赖管理工具maven 一、…

基于yolov2深度学习网络模型的鱼眼镜头中人员检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 load yolov2.mat% 加载训练好的目标检测器 img_size [448,448]; imgPath test/; % 图像…

LeetCode 15 —— 三数之和

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 首先我们对数组进行从小到大排序&#xff0c;然后遍历数组 [ 0 , n u m s . s i z e ( ) − 3 ] [0,nums.size()-3] [0,nums.size()−3] 作为三元组中的 a a a&#xff0c;由于三元组的索引互不相同&#xff0c…

文件与IO基础常识知识

在这里&#xff0c;只介绍理论知识&#xff0c;不介绍代码。 目录 1.IO 1.1.字面概念 1.2.输入输出模型 2.文件 2.1.文件目录 2.2.文件路径 2.3.文件分类 1.IO 为了我们接下来学习的文件IO&#xff0c;所以我们先来认识什么是IO。 1.1.字面概念 &#xff08;1&#x…

【知识加油站】——机电产品数字孪生机理模型构建

明确一种多领域、多层次、参数化、一致性的机电一体化装备数字孪生机理模型构建准则&#xff01; 关键词英文简称&#xff1a; 数字孪生&#xff1a;DT物联网&#xff1a;IoT网络物理系统&#xff1a;CPS高级架构&#xff1a;HLA统一建模语言&#xff1a;UML数控机床&#xf…

Sarcasm detection论文解析 |A2Text-Net:一种用于讽刺检测的新型深度神经网络

论文地址 论文地址&#xff1a;A2Text-Net: A Novel Deep Neural Network for Sarcasm Detection | IEEE Conference Publication | IEEE Xplore github:lliyuan1117/A2Text-Net (github.com) 论文首页 A2Text-Net&#xff1a;一种用于讽刺检测的新型深度神经网络 &#x1f4c5…

Win11 怎么让软件运行后台全部显示在任务栏上 win11任务栏展开显示所有软件图标

Win11 怎么让软件运行后台全部显示在任务栏上 win11任务栏展开显示所有软件图标 方法二 搜索cmd 打开命令行面板 然后输入 explorer shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}就能显示出来了 ## 方法三 通知区域图标不存在 如图&#xff0c;显示为这样 这种时候桌面…

深入解析Java中的String对象及其性能优化

作者主页&#xff1a; &#x1f517;进朱者赤的博客 精选专栏&#xff1a;&#x1f517;经典算法 作者简介&#xff1a;阿里非典型程序员一枚 &#xff0c;记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; ❤️觉得文章还…

uniapp乡村社区户籍问外来人员管理系统 微信小程序python+java+node.js+php

基于微信小程序的外来人员管理系统项目的概述设计分析&#xff0c;主要内容有的私教预约平台系统平台的具体分析&#xff0c;进行数据库的是设计&#xff0c;数据采用MySQL数据库&#xff0c;并且对于系统的设计采用比较人性化的操作设计&#xff0c;对于系统出现的错误信息可以…

用Jenkins Gerrit-Trigger插件实现提交gerrit后自动启动编译验证-解决编译依赖问题

用Jenkins Gerrit-Trigger插件实现提交gerrit后自动启动编译验证-CSDN博客讨论了如何利用插件在提交gerrit的时候自动出发一个jenkins job编译固件,但是没有解决编译依赖问题。本文提出一种解决方案 首先在git commit -m ""的时候在commit message中设置Depend-On:…

Typescript基础语法(四)

模块化 模块化是指将复杂的程序拆解为多个独⽴的⽂件单元&#xff0c;每个⽂件被称为⼀个模块。在 TypeScript 中&#xff0c;默认情况下&#xff0c;每个模块都拥有⾃⼰的作⽤域&#xff0c;这意味着在⼀个模块中声明的任何内容&#xff08;如变量、函数、类等&#xff09;在该…

我们的手机是如何连接上网的?骨干网又是什么?

什么是骨干网&#xff08;Backbone Network&#xff09; 几台计算机连接起来&#xff0c;互相可以看到其他人的文件&#xff0c;这叫局域网。整个城市的计算机都连接起来&#xff0c;就是城域网。把城市之间连接起来的网就叫骨干网。 这些骨干网是国家批准的可以直接和国外连…

CUDA CPP Unity Compute Shader

为学 开始一个新的学习计划&#xff0c;涵盖&#xff1a; 主题学习内容CUDAProfessional CUDA C Programming/NVIDIA CUDA初级教程视频(周斌)CCPrimer / The Cherno CPPUnity Compute ShaderUdemy Learn to Write Unity Compute ShadersLinear AlgebraMIT 18.06 Prof.Gilbert…

【Anaconda 3 】Jupyter Notebook 的安装配置及使用

Jupyter Notebook 的安装配置及使用 一、引言 Jupyter Notebook 是一种交互式笔记本&#xff0c;它允许用户将代码、注释、方程式、可视化内容等整合到一个文档中&#xff0c;并支持多种编程语言&#xff0c;如 Python、R、Julia 等。它在数据科学、机器学习和教育领域中得到…
最新文章