学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

179

积分

0

好友

22

主题
发表于 前天 16:31 | 查看: 14| 回复: 0
来自:阿Q技术站


一面
1、C++结构体和类的区别,类默认的访问权限,结构体可以定义成员函数吗?

1. 默认访问权限

  • 结构体(struct):成员变量和成员函数默认是 public 访问权限。
  • 类(class):成员变量和成员函数默认是 private 访问权限。


struct MyStruct {
    int x;          // 默认是 public
    void foo() {}   // 默认是 public
};

class MyClass {
    int y;          // 默认是 private
    void bar() {}   // 默认是 private
};

2. 语法上和使用上的区别

  • 定义方式:虽然 struct 和 class 可以用来定义数据成员和成员函数,但使用 class 更常见于表示具有行为和状态的对象,而 struct 更常用于表示纯粹的数据结构。
  • 继承:在继承时,class 的继承默认是 private,而 struct 的继承默认是 public。


struct Base1 {};
class Base2 {};

// 继承默认权限不同
struct Derived1 : Base1 {}; // public 继承
class Derived2 : Base2 {};  // private 继承

3. 结构体是否可以定义成员函数

C++ 的 struct 可以定义成员函数。实际上,struct 和 class 除了默认访问权限不同外,语法上几乎是一样的。

struct MyStruct {
    int x;
    void setX(int val) {
        x = val;
    }
    int getX() {
        return x;
    }
};

2、多态的意义?
多态指的是同一个接口可以有不同的实现方式。多态通过允许不同类型的对象以相同的方式进行处理,极大地提高了代码的灵活性和可扩展性。多态主要通过继承和接口实现,并且可以分为编译时多态和运行时多态。

多态的意义
1. 提高代码重用性和可维护性: 多态允许你编写更加通用的代码。例如,可以编写一个函数来处理不同类型的对象,而不需要了解这些对象的具体类型。这样,当需要增加新的类型时,只需要新增类的实现,而不需要修改已经存在的代码。

// 基类
class Animal {
public:
    virtual void makeSound() = 0; // 纯虚函数
};

// 派生类
class Dog : public Animal {
public:
    void makeSound() override {
        cout << "Woof" << endl;
    }
};

class Cat : public Animal {
public:
    void makeSound() override {
        cout << "Meow" << endl;
    }
};

void makeAnimalSound(Animal* animal) {
    animal->makeSound();
}

int main() {
    Dog dog;
    Cat cat;
    makeAnimalSound(&dog); // 输出 Woof
    makeAnimalSound(&cat); // 输出 Meow
}

2. 简化代码: 多态可以用统一的接口来操作不同类型的对象,简化了代码的复杂度和可读性。例如,在上面的代码中,无论是 Dog 还是 Cat,你都可以通过调用 makeSound 来发出声音,而不需要分别为每种类型写不同的处理逻辑。

3. 增强系统的扩展性: 多态使得系统更容易扩展。当需要添加新的功能时,只需要新增实现类,而不需要修改现有的代码。例如,如果需要新增一个 Bird 类,只需要继承 Animal 并实现 makeSound 方法。

4. 实现动态绑定: 通过多态,程序在运行时可以根据对象的实际类型进行方法调用,而不是在编译时确定调用哪个方法。这种动态绑定使得程序更加灵活和动态。

多态的实现方式
  • 继承:通过继承基类的接口并重写其方法,子类可以表现出不同的行为。
  • 虚函数:在基类中定义虚函数(virtual functions),并在子类中重写这些虚函数。通过基类指针或引用调用虚函数时,会调用实际对象的实现。
  • 接口:在某些语言(如 Java 和 C#)中,通过实现接口(interface)来实现多态。接口定义了方法的签名,具体的实现由类提供。


3、重载和重写的区别?

重载(Overloading)
重载是指在同一个类中定义多个同名方法,但这些方法具有不同的参数列表(参数类型或参数个数)。编译器根据方法的参数列表来区分这些方法。在C++中,构造函数也可以被重载。

特点
  • 方法名相同:重载的方法必须具有相同的名称。
  • 参数列表不同:重载的方法必须具有不同的参数列表(参数类型或参数个数)。
  • 返回类型可以不同:虽然返回类型可以不同,但返回类型不是区分重载方法的依据。
  • 同一个类中:重载的方法必须定义在同一个类中。


例子

class Print {
public:
    void display(int i) {
        cout << "整数: " << i << endl;
    }
    void display(double f) {
        cout << "浮点数: " << f << endl;
    }
    void display(string s) {
        cout << "字符串: " << s << endl;
    }
};

int main() {
    Print obj;
    obj.display(5);      // 调用 display(int)
    obj.display(3.14);   // 调用 display(double)
    obj.display("Hello");// 调用 display(string)
    return 0;
}

重写(Overriding)
重写是指子类重新定义从基类继承的方法,目的是提供子类自己的实现版本。重写的方法必须具有相同的名称、参数列表和返回类型。重写通常与多态(Polymorphism)结合使用。

特点
  • 方法名相同:重写的方法必须具有与基类方法相同的名称。
  • 参数列表相同:重写的方法必须具有与基类方法相同的参数列表。
  • 返回类型相同:重写的方法必须具有与基类方法相同的返回类型。
  • 基类和子类之间:重写的方法在基类中声明,在子类中实现。
  • 虚函数:在C++中,基类方法通常需要声明为虚函数(virtual)以允许子类重写。


例子

class Animal {
public:
    virtual void makeSound() {
        cout << "Animal sound" << endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override { // 重写基类的 makeSound 方法
        cout << "Woof" << endl;
    }
};

int main() {
    Animal* animal = new Dog();
    animal->makeSound(); // 调用的是 Dog 类的 makeSound 方法
    delete animal;
    return 0;
}

顺便吆喝一下,技术大厂,前后端测试,来看看

4、TCP/IP 三次握手的过程,为什么要3次?
三次握手

后端开发面经系列 -- 华为OD -- C++面经(1)

后端开发面经系列 -- 华为OD -- C++面经(1)


在建立连接之前,Client处于CLOSED状态,而Server处于LISTEN的状态。

1. 第一次握手(SYN-1):
客户端发送一个带有 SYN 标志的 TCP 报文段给服务器,表示客户端请求建立连接。
客户端选择一个初始序列号(ISN)并将其放入报文段中,进入 SYN_SENT 状态。

2. 第二次握手(SYN + ACK):
服务器收到客户端发送的 SYN 报文段后,如果同意建立连接,会发送一个带有 SYN 和 ACK 标志的报文段给客户端,表示服务器接受了客户端的请求,并带上自己的 ISN。
服务器进入 SYN_RCVD 状态。

3. 第三次握手(ACK):
客户端收到服务器发送的 SYN+ACK 报文段后,会发送一个带有 ACK 标志的报文段给服务器,表示客户端确认了服务器的响应。
客户端和服务器都进入 ESTABLISHED 状态,连接建立成功,可以开始进行数据传输。

为什么需要三次握手?

1. 确保双方都能发送和接收数据:
第一次握手确认客户端的发送能力和服务器的接收能力。
第二次握手确认服务器的发送能力和客户端的接收能力。
第三次握手确认客户端的发送能力和服务器的接收能力。

2. 防止旧的连接请求误导双方:
通过三次握手,双方都能确认对方的状态是最新的,有效避免了网络中的旧的、延迟的SYN包造成的错误连接。

3. 防止重复数据包干扰:
三次握手确保双方都能有效处理重复的数据包,并建立一个唯一的连接。

5、进程和线程的区别?
定义

进程(Process):
进程是操作系统分配资源的基本单位。每个进程有自己独立的内存空间,包括代码段、数据段、堆、和栈。
进程之间相互独立,进程的创建、执行和销毁都是由操作系统管理的。

线程(Thread):
线程是进程的一个执行单元,是CPU调度的基本单位。一个进程可以包含多个线程,这些线程共享进程的资源(如内存和文件描述符)。
线程之间的切换比进程切换更轻量,因为线程共享进程的资源,不需要频繁的资源分配和回收。

区别

1. 内存和资源:
进程:每个进程都有自己独立的地址空间和资源,相互之间不会直接干涉。进程之间的通信需要通过进程间通信(IPC)机制,如管道、消息队列、共享内存等。
线程:线程共享同一个进程的地址空间和资源,所以线程之间的通信更加直接、快速,但也带来了一些同步和互斥的问题。

2.创建和销毁:
进程:创建和销毁进程的开销较大,因为操作系统需要为进程分配和回收大量的资源。
线程:创建和销毁线程的开销较小,因为线程共享进程的资源,不需要重新分配内存。

3. 切换开销:
进程:进程切换需要上下文切换,包括保存和恢复寄存器、内存映射等,开销较大。
线程:线程切换开销较小,因为线程共享同一进程的上下文,只需要保存和恢复少量的状态信息。

4. 独立性和安全性:
进程:由于进程独立,进程间的错误不会相互影响,一个进程崩溃不会影响其他进程。
线程:由于线程共享资源,一个线程的错误(如内存泄漏、死锁)可能影响整个进程中的其他线程。

使用场景
进程:适用于需要高独立性和安全性的任务,比如不同用户的程序、服务和应用之间的隔离。
线程:适用于需要高效并发的任务,如多线程服务器、并行计算等,需要在同一进程内执行多个任务。


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2024-11-21 14:48 , Processed in 0.136253 second(s), 37 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表