【问题标题】:Multiple inheritance and the this pointer多重继承和this指针
【发布时间】:2012-01-27 15:20:17
【问题描述】:

假设我有这个结构:

struct vector_data
{
    double x, y;

    double& operator[](size_t index)
    {
        return * (static_cast<double*>(static_cast<void*>(this)) + index);
    }
};

operator[] 应该按预期工作,因为 vector_data 是 POD 类型。 预期的行为是 vector_data[0] 返回 x,vector_data[1] 返回 y。

现在假设我有第二个结构:

struct more_data
{
    double evil_data;

    // There could be more here, data or functions
};

并像这样从两者派生:

struct composed : public more_data, public vector_data
{
};

这会破坏 operator[] 的预期行为吗?也就是说,派生结构体中vector_data的this-pointer还是会指向结构体的vector_data部分,还是会指向派生结构体的开头?

如果它确实破坏了 operator[],那么我该如何解决这个问题?我可以先从 vector_data 继承,但假设组合包含虚函数。我知道大多数编译器将 vtable 放在最后,但这不能保证。最好的方法是什么?

【问题讨论】:

  • 您正在对 void* 进行指针算术运算,什么应该完全按预期工作(或者更确切地说,您的预期是什么意思)?
  • 查看编辑。这只是一个更通用问题的示例:this-pointer 指向什么?
  • 我知道这只是一个例子,但是void*指针上的算术没有定义,内部转换是没用的。
  • 有时编译器会抱怨它不能将 x 类型的指针转​​换为 y 类型,因此首先转换为 void 指针可以解决这个问题。
  • 不能只根据index的值返回x或者y吗?

标签: c++ multiple-inheritance reinterpret-cast


【解决方案1】:

撇开不正确的指针算术问题(xy 之间的填充的可能性使您的假设无效),这里是使用多重继承时 this 指针发生了什么的快速说明:

#include <iostream>
using namespace std;

struct a {
    int aa;
    void showA() {
        cerr << this << endl;
    }
};
struct b {
    int bb;
    void showB() {
        cerr << this << endl;
    }
};
struct c : public a, b {
    int cc;
    void showC() {
        cerr << this << endl;
    }
};
int main() {
    c x;
    x.showA();
    x.showB();
    x.showC();
}

showAshowB 打印不同的数字; showC 打印与showA 相同的数字,因为a 在碱基列表中列在首位。如果您在那里切换ab,那么showCshowB 将是相同的。 “魔法”在 C++ 编译器中:它足够聪明,可以给每个成员函数一个正确的this 指针。

【讨论】:

    【解决方案2】:

    你想要的可能是这样的:

    struct vector_data
    {
       union 
       {
            struct 
            {
                double x, y;
            }; 
            double data[2];
       }; 
    
       double& operator[](size_t index)
       {
           return data[index];
       }
    }
    

    【讨论】:

    • 这大致是我想要实现的,但这样做的问题是它也暴露了数据成员。
    • 请注意,将其成员“溢出”到周围类中的未命名联合和结构是 MSVC 扩展,而不是标准 C++,因此不可移植。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    相关资源
    最近更新 更多