多重继承和this指针

4

Suppose I have this struct:

struct vector_data
{
    double x, y;

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

由于 vector_data 是一个 POD 类型,所以 operator[] 应该按预期工作。

预期的行为是 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指针是否仍然指向结构体的vector_data部分,还是指向派生结构体的开头?

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


1
你正在对 void* 进行指针算术运算,那么什么是预期的结果(或者更确切地说,你所谓的“预期”是什么)? - Mat
我知道这只是一个例子,但是在void*指针上进行算术运算是没有定义的,内部转换是无用的。 - Mat
你不能根据index的值返回x或y吗? - Yaniro
阿马特,现在我明白你所说的错误算术了。我忘记了)。雅尼罗:是的,我可以,但使用偏移量会比这个更快吗? - Ruud
为什么不直接使用reinterpret_cast,而是要用static_cast<double*>(static_cast<void*>呢? - curiousguy
显示剩余2条评论
2个回答

7

先不管你错误的指针算法(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指针。


1

可能你想要的是这样的:

struct vector_data
{
   union 
   {
        struct 
        {
            double x, y;
        }; 
        double data[2];
   }; 

   double& operator[](size_t index)
   {
       return data[index];
   }
}

这大致是我想要实现的,但问题在于它也会暴露数据成员。 - Ruud
1
请注意,未命名的联合体和结构体“溢出”其成员到周围类中是MSVC扩展,不是标准C ++,因此不可移植。 - Xeo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接