首页 > 编程语言 >C++面试基础系列-this指针

C++面试基础系列-this指针

时间:2024-08-27 15:53:49浏览次数:14  
标签:函数 对象 成员 C++ 面试 指针 public speak

系列文章目录


文章目录


C++面试基础系列-this指针

Overview

1.this指针

在 C++ 中,this 指针是一个特殊的指针,它在每个非静态成员函数中自动可用。this 指向调用成员函数的当前对象实例。以下是 this 指针的一些关键特性和用法:

1.1.特性

  1. 隐式存在:在成员函数中,this 指针隐式地可用,不需要定义或声明。

  2. 指向当前对象this 指针指向调用成员函数的对象。

  3. 类型为当前类的指针this 的类型是成员函数所在类的指针类型。

  4. 在静态成员函数中不可用:由于静态成员不属于任何对象实例,因此在静态成员函数中 this 指针不可用。

  5. 用于区分成员变量和局部变量:当局部变量名与成员变量名相同时,this 可以用来区分它们。

1.2.用法

  1. 访问成员变量

    class MyClass {
        int value;
    public:
        void setValue(int v) {
            this->value = v; // 使用 this 指针访问成员变量
        }
    };
    
  2. 调用其他成员函数

    class MyClass {
        void doSomething() {
            // ...
        }
    public:
        void execute() {
            this->doSomething(); // 使用 this 指针调用另一个成员函数
        }
    };
    
  3. 在构造函数中使用

    class MyClass {
    public:
        MyClass(int v) {
            this->setValue(v); // 在构造函数中使用 this 指针调用成员函数
        }
        void setValue(int v) {
            // ...
        }
    };
    
  4. 实现赋值运算符

    class MyClass {
        int value;
    public:
        MyClass& operator=(const MyClass& other) {
            if (this != &other) { // 检查自赋值
                this->value = other.value;
            }
            return *this; // 返回当前对象的引用
        }
    };
    
  5. 用于多态
    当涉及到多态时,this 指针可以被转换为派生类的指针:

    class Base {
    public:
        virtual ~Base() {}
    };
    
    class Derived : public Base {
        int extraValue;
    public:
        void process() {
            // 安全地将 this 转换为 Derived 类型的指针
            Derived* d = dynamic_cast<Derived*>(this);
            // 使用 d 指针
        }
    };
    
  6. 在 lambda 表达式中使用
    在成员函数中定义的 lambda 可以捕获 this 指针:

    class MyClass {
    public:
        void execute() {
            int value = 10;
            [=](){ // 通过值捕获 this 指针
                doSomething();
            }();
        }
        void doSomething() {
            // ...
        }
    };
    
  7. 避免对象复制
    使用 this 指针实现深拷贝或浅拷贝逻辑。

1.3.注意事项

  • 应谨慎使用 this 指针,避免不必要的使用,因为它可能会使代码的意图不够明确。
  • 在多态情况下,使用 dynamic_cast 转换 this 指针时,只有在含有虚函数的类中才有效。
  • 在构造函数和析构函数中也可以使用 this 指针,但要确保使用方式是安全的,因为这些特殊时期对象可能未完全构造或正在被销毁。

this 指针是 C++ 中一个强大的特性,正确使用它可以提高代码的灵活性和表达能力。

当然可以。在 C++ 中,多态性通常通过虚函数实现,而 this 指针在多态类中可以用来调用成员函数或访问成员变量,尤其是在需要明确对象类型时。以下是一个使用 this 指针的多态类的示例:

2.使用 ‘this’ 指针的多态类的示例

#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 基类
class Animal {
public:
    virtual ~Animal() {}

    // 虚函数,用于多态
    virtual void speak() const {
        std::cout << "Some generic animal sound" << std::endl;
    }

    // 使用 this 指针调用其他成员函数
    void performAction() {
        std::cout << "The animal is performing an action." << std::endl;
        this->speak(); // 调用虚函数
    }
};

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

class Cat : public Animal {
public:
    void speak() const override {
        std::cout << "Meow! Meow!" << std::endl;
    }
};

// 使用多态和 this 指针
void makeAnimalsSpeak(const std::vector<std::shared_ptr<Animal>>& animals) {
    for (const auto& animal : animals) {
        // 通过 this 指针明确调用 speak 函数
        ((Animal*)this)->speak(); // 错误的使用示例,仅用于说明 this 的作用
        animal->speak(); // 正确的多态调用
    }
}

int main() {
    std::vector<std::shared_ptr<Animal>> animals;
    animals.push_back(std::make_shared<Dog>());
    animals.push_back(std::make_shared<Cat>());

    makeAnimalsSpeak(animals);

    return 0;
}

在这个示例中:

  • Animal 是一个基类,有一个虚函数 speak() 和一个非虚函数 performAction()performAction() 使用 this 指针调用 speak(),展示了如何在类内部使用 this 指针调用成员函数。
  • DogCat 是从 Animal 派生的子类,它们重写了 speak() 函数,提供了具体的实现。
  • makeAnimalsSpeak() 函数接受一个 Animal 指针的 std::vector,并调用每个动物的 speak() 函数。这里展示了如何通过多态性使用 this 指针。注意,示例中的 ((Animal*)this)->speak(); 是错误的用法,仅用于说明 this 的作用。正确的用法是 animal->speak();,它利用了多态性调用正确的 speak() 版本。
  • main() 函数中,我们创建了一个 Animal 对象的向量,其中包括 DogCat 的实例,并调用 makeAnimalsSpeak() 来演示多态性。

这个示例展示了如何在多态上下文中使用 this 指针,以及如何在派生类中重写虚函数来实现不同行为。

3.在C++中,指针和对象本身有什么区别?

在 C++ 中,指针和对象本身有几个关键的区别:

  1. 存储内容

    • 对象:对象是实际的数据实体,它占用内存并包含数据和可能的行为(通过成员函数)。
    • 指针:指针是一个变量,它存储的是另一个对象的内存地址。
  2. 内存占用

    • 对象:对象的大小通常比指针大,因为它包含了实际的数据。
    • 指针:指针的大小在 32 位系统上通常是 4 字节,在 64 位系统上是 8 字节,与它所指向的对象大小无关。
  3. 访问数据

    • 对象:可以直接访问对象的成员变量和函数。
    • 指针:需要使用解引用操作符(*)来访问指针指向的对象的成员。
  4. 生命周期

    • 对象:对象有自己的生命周期,它可能在栈上自动创建和销毁,或在堆上通过 newdelete 进行管理。
    • 指针:指针本身有自己的生命周期,但它指向的对象可能有不同的生命周期。
  5. 别名

    • 对象:对象通常只有一个标识符。
    • 指针:可以通过多个指针引用同一个对象(别名),这可能导致复杂的内存管理问题。
  6. 可变性

    • 对象:对象的地址在声明后通常不会改变(除非使用 std::move)。
    • 指针:指针的值(即它所指向的地址)可以在运行时改变。
  7. 数组和指针

    • 对象:不能直接将对象视为数组来处理。
    • 指针:指针可以进行算术运算(如加法和减法),这使得指针可以像数组一样使用。
  8. 传递性能

    • 对象:按值传递对象可能会涉及复制构造函数,这可能代价昂贵。
    • 指针:指针传递的是地址,通常是很小的数据量,开销较小。
  9. 安全性

    • 对象:使用对象通常更安全,因为它们不允许悬空或未定义的状态。
    • 指针:指针需要小心管理,不当使用可能导致悬空指针、野指针或内存泄漏。
  10. 语法

    • 对象:使用变量名直接访问。
    • 指针:需要通过 -> 运算符来访问指针指向的对象的成员。

理解指针和对象之间的区别对于编写有效和安全的 C++ 程序至关重要。指针提供了强大的灵活性,但也需要更多的注意力来确保正确管理内存和对象的生命周期。


关于作者

标签:函数,对象,成员,C++,面试,指针,public,speak
From: https://blog.csdn.net/wesigj/article/details/141582899

相关文章

  • c/c++代码流程图生成
    以下介绍2款皆免费1.cxx2flow【github项目】c/c++函数解析为dot然后通过Graphviz渲染项目有附带gui程序可直接生成流程图,但是显示效果缩放不太行,建议解析生成dot后喂给其他基于Graphviz的渲染服务,使用过vscode上面的graphviz-interactive-preview,效果还行,也有在线网页渲染......
  • 【编程规范具体案例(基于Qt、微软、谷歌和AUTOSAR C++14 参考)】 C++ 编码规范 之并发篇
    目录标题并发目录12.并发编程规范12.1线程创建与管理规则12.1.1\[必须]明确定义线程的生命周期管理策略12.1.2\[必须]为关键线程设置明确的标识符12.1.3\[必须]在多线程环境中安全地处理异常12.2线程同步规则12.2.1\[必须]使用线程安......
  • C++与C语言中基础数据类型详解
    目录引言基础数据类型分类实际编程中的应用建议结论引言在C++与C语言的编程世界中,理解并正确使用基础数据类型是每个程序员的必备技能。不同的数据类型在内存中的占用和表示方式直接影响到程序的性能和行为。本文将详细介绍C++与C语言中常见的基础数据类型,探讨它们......
  • C++ lambda
    文章目录基本语法捕捉列表函数对象与lambda表达式C++的lambda表达式是C++11及以后版本中引入的一种强大的特性,它提供了一种简洁的方式来定义匿名函数对象。Lambda表达式能够捕获其所在作用域中的变量(以值或引用的方式),并允许你在需要函数对象的地方(比如算法库中的函数......
  • C++常见内存错误及其对策
    常见内存错误及其对策目录常见内存错误及其对策内存分配未成功,却使用了它内存分配成功但未初始化内存操作越界内存泄漏释放内存后继续使用规则总结图表示C++学习资料在软件开发过程中,内存管理是至关重要的一环。内存错误不仅会导致程序崩溃,还可能引发安全问题。本文......
  • 面试官:Leader崩溃Follower不够新怎么办?
    这是一道非常经典的Kafka问题,是关于Leader在“异常”情况下的选举问题。背景我们知道Kafka中的Partition(分区)是存储消息的最终介质,但Partition又有两种分类:LeaderPartition:主分区,负责数据写入和读取。FollowerPartition:副本分区,用于数据备份和主节点宕机之后的分......
  • c++教程之三大结构
    C++顺序结构教程在编程的世界里,顺序结构是构建所有程序的基础。无论是简单的脚本还是复杂的应用程序,它们都是由一系列按照特定顺序执行的指令组成的。C++,作为一种高效、灵活的编程语言,同样遵循这一原则。本教程将深入介绍C++中的顺序结构,包括变量与数据类型、运算符与表达式、......
  • 程序员必备的的5个刷题网站。大厂面试稳了 力扣 https://leetcode.cn
    程序员必备的的5个刷题网站。大厂面试稳了力扣https://leetcode.cn1、leetcode力扣。网址:https://leetcode.cnLeetCode是一个定位为求职的刷题网站,其中又以算法题为主。很多大厂在面试的时候,都会考算法。有空就刷一刷这里面的算法题,你的算法水平肯定会有大幅的提升,不管是求职,......
  • C++笔记9•list•
    容器之list1.list的介绍(1).list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。(2).list的底层是双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。(3).优......
  • C++学习 — 函数
    目录1.概述2.函数的定义3.函数的调用4.值传参5.函数的常见样式6.函数的声明7.函数的分文件编写8.函数默认参数 9.函数占位参数10.函数重载(1)函数重载概述(2)函数重载注意事项1.概述作用:将一段经常使用的代码封装起来,减少重复代码   一个较大的程序,一般......