当前位置: 首页 > 知识库问答 >
问题:

C++编译器如何处理虚函数中的“this”指针

微生耘豪
2023-03-14

我对C++编译器如何处理虚函数中的“this”指针有一个困惑,我的代码是:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>

using namespace std;



class A {
        public:
                void print_A(void) {
                        cout << "A::THIS = " << this << endl;

                        return;
                }

                int a;

        virtual ~A(void) {
                return;
        }
};

class B {
        public:
                virtual void print(void) {
                        cout << "B::THIS = " << this << endl;

                        return;
                }

                int b;
};

class C: public A, public B {
        public:
                void print(void) {
                        cout << "C::THIS = " << this << endl;

                        return;
                }

                int c;
};


class D {
        public:

                int d;

                virtual ~D(void) {
                        return;
                }
};


class E: public D, public C {
        public:
                int e;

                virtual ~E(void) {
                        return;
                }
};

void global_print(B *pb) {
        cout << "pb = " << pb << endl;
        pb->print();

        return;
}

int main(int argc, char *argv[]) {

        E e;
        A *pa = &e;
        B *pb = &e;
        C *pc = &e;
        D *pd = &e;
        E *pe = &e;


        cout << "pa = " << pa << endl;
        cout << "pb = " << pb << endl;
        cout << "pc = " << pc << endl;
        cout << "pd = " << pd << endl;
        cout << "pe = " << pe << endl;

        pb->print();
        pc->print();
        pe->print();


        global_print(&e);
        return 0;

这是在我的Linux中用G++编译的结果:

pa = 0x7ffc1e7c7a80
pb = 0x7ffc1e7c7a90
pc = 0x7ffc1e7c7a80
pd = 0x7ffc1e7c7a70
pe = 0x7ffc1e7c7a70
C::THIS = 0x7ffc1e7c7a80
C::THIS = 0x7ffc1e7c7a80
C::THIS = 0x7ffc1e7c7a80
pb = 0x7ffc1e7c7a90
C::THIS = 0x7ffc1e7c7a80

我无法理解我将&e发送到global_printglobal_print中的pb等于0x7FFC1E7C7A90。然后调用pb->print()global_print中的这个指针是0x7FFC1E7C7A80,与pc相同。似乎pb->print()将B类转换为C类,但B类是C类的父类,如何转换?

虽然pb可以通过虚函数获得C::print的地址,但是要将B类转换为C类,需要知道的只是一个没有足够信息的地址,那么程序在运行时是如何知道B类转换为C类的呢?

多谢!祝你有一个愉快的一天!

共有1个答案

鲍驰
2023-03-14

    #include<iostream>
    
    class D
    {
    public:
        D() {
            std::cout << "This is constructor for D class." << std::endl;
        };
        ~D() {
            std::cout << "This is destructor for D class." << std::endl;
        };
    protected:
        int variable = 123456;
    };
    class B :
        virtual public D
    {
    public:
        B() {
            std::cout << "This is constructor for B class." << std::endl;
        };
        ~B() {
            std::cout << "This is destructor for B class." << std::endl;
        };
    private:
    
    };
    class C :
        virtual public D
    {
    public:
        C() {
            std::cout << "This is constructor for C class." << std::endl;
        };
        ~C() {
            std::cout << "This is destructor for C class." << std::endl;
        };
    private:
    
    };
    class A : 
        public B, public C
    {
    public:
        A() {
            std::cout << "This is constructor for A class." << std::endl;
        };
        ~A() {
            std::cout << "This is destructor for A class." << std::endl;
        };
        void function() {
            std::cout << "Variable: " << variable << std::endl;
        }
    
    private:
    
    };
    
    int main() {
        
        A a;
        std::cout << std::endl;
        a.function();
        std::cout << std::endl;
    
        return 0;
    }

编译器不知道哪个类的变量或方法必须继承。为此,我们使用virtual关键字。我们对编译器说,由于virtual关键字,编译器只继承一个成员。

class B : virtual public D
......
class C : virtual public D
......

尽可能避免多重继承是必须的!

代码输出:

This is constructor for D class.
This is constructor for B class.
This is constructor for C class.
This is constructor for A class.
Variable: 123456
This is destructor for A class.
This is destructor for C class.
This is destructor for B class.
This is destructor for D class.
 类似资料:
  • 我试着实现了一个列表容器,并决定将一些通用函数如< code>sum()移到基类,这样我就可以在其他容器中重用它们。 所有的基本支持类需要的是三个方法 empty()、 和 。我不能使这些纯粹的虚拟,因为支持类永远不会被实例化。但它仍然必须使用这些方法来实现自己的方法,如 我试过这样的东西: 但是尝试使用< code>sum()会导致编译错误 对于、和中的每一个。 有什么建议吗?

  • 预处理指令 C语言规定:源程序中可以加入一些预处理指令。但预处理指令并不是C语言本身的组成部分,编译器不能识别它们,不能直接对这些指令进行编译。在使用时需要以“#”开头,用以与C语言区分。 所谓预处理,就是指源程序在进行编译的第一遍扫描(词法分析和语法分析)之前所做的工作由预处理程序完成。当对一个源程序进行编译时,系统将自动引用预处理程序对源程序中的预处理部分进行处理(代替),处理完毕自动进入对源

  • C++ 类 & 对象 在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。 友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。 下面的实例有助于更好地理解 this 指针的概念:#include <iostream> using namespace std; c

  • null 代码(步骤1和2): 实际上,第一个任务执行良好,并为注释处理器实现编译.class文件。它在第二个任务停止。 Ant说: Java 1.6 Ant 1.8.2

  • 本文向大家介绍解析C++中的字符串处理函数和指针,包括了解析C++中的字符串处理函数和指针的使用技巧和注意事项,需要的朋友参考一下 C++字符串处理函数 字符串连接函数 strcat 其函数原型为 strcat是string catenate(字符串连接)的缩写。该函数有两个字符数组的参数,函数的作用是:将第二个字符数组中的字符串连接到前面字符数组的字符串的后面。第二个字符数组被指定为const,