代码随想录八股训练营第二十九天| C++

前言

一、C++面向对象的三大特性:

1.1.封装(Encapsulation):

1.2.继承(Inheritance):

1.3.多态(Polymorphism):

1.4.总结:

二、简述一下C++的重载和重写,以及它们的区别和实现方式?

2.1. 重载(Overloading):

2.2. 重写(Overriding):

2.3.区别:

三、C++怎么实现多态??

3.1.编译时多态(静态多态):

3.2.1.函数重载:

3.1.2.模板:

3.2.运行时多态(动态多态):

3.2.1.虚函数:

3.2.2.纯虚函数和抽象类:

3.2.2.纯虚函数和抽象类:

四、虚函数和纯虚函数的区别?

4.1.虚函数(Virtual Function):

4.2.纯虚函数(Pure Virtual Function):

4.3.区别:

总结


前言

在C++编程语言中,面向对象编程(OOP)是一种核心的编程范式,它通过封装、继承和多态等概念来提高代码的可重用性、灵活性和可维护性。本文将深入探讨C++中的这些面向对象特性,以及如何在实际编程中应用它们。我们还将讨论重载和重写的概念,以及如何在C++中实现多态性。通过这些讨论,我们希望读者能够更好地理解C++的OOP特性,并有效地将它们应用于解决实际问题。


一、C++面向对象的三大特性:

C++是一种支持面向对象编程(Object-Oriented Programming, OOP)的编程语言。面向对象编程是一种编程范式,它将现实世界中的实体抽象为对象,通过对象之间的交互来设计软件。面向对象编程的三大特性包括:

1.1.封装(Encapsulation):

  • 封装是将数据(属性)和操作这些数据的代码(方法)捆绑在一起的过程。在C++中,这通常是通过类(class)来实现的。类可以包含私有(private)和公有(public)成员,私有成员不能被类外部直接访问,这样可以隐藏内部实现细节,保护对象的状态不被外部直接修改,只通过类提供的公有方法(如getter和setter)来访问和修改。

1.2.继承(Inheritance)

  • 继承是一种可以让新创建的类(派生类或子类)接收另一个类(基类或父类)的属性和方法的机制。这允许代码重用,并可以创建出类之间的层次结构。在C++中,使用:关键字来指定继承关系。继承支持多态性,即同一个操作作用于不同的对象时,可以有不同的解释和不同的执行结果。

1.3.多态(Polymorphism)

  • 多态是指对象可以有多种形式,即同一个接口可以被不同的对象以不同的方式实现。在C++中,多态主要通过虚函数(virtual functions)来实现。当通过基类指针或引用调用虚函数时,会根据对象的实际类型来调用相应的函数,这就是动态多态性。多态性允许编写通用的代码,这些代码可以在不同类型的对象上以不同的方式执行。

1.4.总结:

  • 这三大特性共同构成了面向对象编程的核心,使得C++能够提供强大的抽象和代码复用能力,同时也使得代码更加模块化和易于维护。

二、简述一下C++的重载和重写,以及它们的区别和实现方式?

在C++中,重载(Overloading)和重写(Overriding)是多态性概念的两个重要方面,它们都允许函数或方法具有相同的名称,但行为不同。不过,它们的应用场景和实现方式有所区别。

2.1. 重载(Overloading):

  • 重载是指在同一个作用域内,允许创建多个同名函数,只要它们的参数列表不同即可。参数列表不同可以是参数的类型不同、参数的数量不同,或者是两者都不同。重载是编译时多态性的体现。
//实现方式
class Example {
public:
    void display(int a) { /* ... */ }
    void display(double a) { /* ... */ }
    void display(int a, double b) { /* ... */ }
};

2.2. 重写(Overriding):

  • 重写是指在派生类(子类)中重新定义基类(父类)的虚函数(virtual function)。这是运行时多态性的体现,它允许派生类改变基类虚函数的行为。
//实现方式
class Base {
public:
    virtual void func() { /* ... */ }
};

class Derived : public Base {
public:
    void func() override { /* ... */ } // 重写基类的func函数
};

2.3.区别:

  • 作用域:重载可以在同一个类中或全局作用域中,而重写只能在派生类中。
  • 参数列表:重载的函数必须有不同的参数列表,而重写的函数参数列表必须与基类中的虚函数完全相同。
  • 虚函数:重写通常与虚函数一起使用,而重载的函数不需要是虚函数。
  • 多态性:重载是编译时多态性,编译器根据参数类型和数量选择正确的函数;重写是运行时多态性,调用哪个函数取决于对象的实际类型。
  • 使用目的:重载用于函数名相同但行为不同的函数,重写用于改变基类中虚函数的行为。

三、C++怎么实现多态??

在C++中,实现多态性主要有两种方式:编译时多态(静态多态)和运行时多态(动态多态)。下面分别介绍这两种多态性的实现方法。

3.1.编译时多态(静态多态):

编译时多态主要通过函数重载和模板实现。

3.2.1.函数重载

  • 函数重载允许在同一作用域内定义多个同名函数,但它们的参数类型和/或参数数量不同。编译器根据调用函数时提供的参数来决定使用哪个函数。
void print(int i) {
    std::cout << "Printing int: " << i << std::endl;
}

void print(double f) {
    std::cout << "Printing float: " << f << std::endl;
}

void print(const std::string& s) {
    std::cout << "Printing string: " << s << std::endl;
}

3.1.2.模板

  • 模板提供了一种方式来定义泛型函数或类,它们可以在多种数据类型上操作。
template 
void print(T value) {
    std::cout << "Printing value: " << value << std::endl;
}

3.2.运行时多态(动态多态):

  • 编译时多态主要通过函数重载和模板实现。

3.2.1.虚函数

  • 在基类中声明虚函数(使用 virtual 关键字),然后在派生类中重写这些虚函数。通过基类的指针或引用调用虚函数时,会根据对象的实际类型来调用相应的函数。
class Base {
public:
    virtual void show() const {
        std::cout << "Base show" << std::endl;
    }
};

class Derived : public Base {
public:
    void show() const override {
        std::cout << "Derived show" << std::endl;
    }
};

Base* b = new Derived();
b->show(); // 输出 "Derived show"
delete b;

3.2.2.纯虚函数和抽象类

  • 如果基类中的虚函数被声明为纯虚函数(使用 =0),则该基类成为抽象类,不能直接实例化。这通常用于定义接口。
class Interface {
public:
    virtual void execute() = 0; // 纯虚函数
};

class Concrete : public Interface {
public:
    void execute() override {
        std::cout << "Executing..." << std::endl;
    }
};

3.2.2.纯虚函数和抽象类

  • 运算符也可以被重载为成员函数,这也是一种编译时多态。
class Complex {
public:
    Complex operator+(const Complex& other) const {
        // 实现复数加法
        return Complex();
    }
};

四、虚函数和纯虚函数的区别?

虚函数(Virtual Function)和纯虚函数(Pure Virtual Function)在C++中都是用来实现多态性的关键概念,但它们之间有一些重要的区别:

4.1.虚函数(Virtual Function):

  • 定义:虚函数是在基类中用 virtual 关键字声明的函数,可以在派生类中被重写(Override)。
  • 实现:虚函数在基类中可以有实现,也可以没有。如果提供了实现,那么在派生类中可以不提供新的实现,而是继承基类的实现。
  • 目的:虚函数用于实现运行时多态性,允许通过基类指针或引用调用派生类中重写的函数。
  • 使用:虚函数可以被直接调用,即使是在基类中也可以创建对象并调用虚函数。

4.2.纯虚函数(Pure Virtual Function):

  • 定义:纯虚函数是在基类中用 virtual 关键字声明,并且在声明时赋值为 0 的函数。它没有实现,是一个接口函数。
  • 实现:纯虚函数在基类中没有实现,必须在派生类中提供实现。如果派生类没有提供实现,则派生类也成为抽象类。
  • 目的:纯虚函数用于定义接口,确保派生类遵循基类的约定,即实现某些功能。
  • 使用:含有纯虚函数的类称为抽象类(Abstract Class),不能直接实例化。只能通过指向派生类的指针或引用来调用纯虚函数。

4.3.区别:

  • 实现要求:虚函数可以在基类中有实现,而纯虚函数没有实现,必须在派生类中实现。
  • 类实例化:含有虚函数的类可以实例化,而含有纯虚函数的类不能实例化,因为它们是抽象类。
  • 目的:虚函数用于实现多态性,而纯虚函数用于定义接口和确保派生类实现某些方法。
  • 强制实现:纯虚函数强制派生类提供实现,而虚函数不强制。
class Base {
public:
    virtual void func() { std::cout << "Base func" << std::endl; } // 虚函数
    virtual void pureFunc() = 0; // 纯虚函数
};

class Derived : public Base {
public:
    void func() override { std::cout << "Derived func" << std::endl; } // 重写虚函数
    void pureFunc() override { std::cout << "Derived pureFunc" << std::endl; } // 实现纯虚函数
};

int main() {
    Base b; // 可以实例化
    b.func(); // 调用虚函数

    // Base p; // 错误:不能实例化含有纯虚函数的类
    // p.pureFunc(); // 错误:纯虚函数没有实现

    Derived d; // 可以实例化
    d.func(); // 调用派生类中的重写虚函数
    d.pureFunc(); // 调用派生类中实现的纯虚函数

    return 0;
}

总结

本文深入探讨了C++的面向对象编程特性,包括封装、继承和多态,以及重载与重写的区别。通过理解这些概念,程序员可以更有效地使用C++构建灵活、健壮的软件系统。

你可能感兴趣的:(数据结构)