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

问题描述

我对 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_printpb 中的 global_print 等于 0x7ffc1e7c7a90。然后我调用 pb->print()this pointer 中的 global_print0x7ffc1e7c7a80,它等于 pc。貌似pb->print()把B类转化为C类,但是B类是C类的父类,怎么转化?

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

非常感谢!祝你有美好的一天!

解决方法


    #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.