多重继承和 this 指针

发布于 2024-12-22 14:40:35 字数 786 浏览 0 评论 0原文

假设我有这个结构:

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
{
};

这会破坏运算符[]的预期行为吗?换句话说,派生结构中的 vector_data 的 this 指针是否仍指向该结构的 vector_data 部分,还是指向派生结构的开头?

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

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);
    }
};

The operator[] should work as expected, because vector_data is a POD type.
The expected behaviour is that vector_data[0] returns x, and vector_data[1] returns y.

Now suppose I have a second struct:

struct more_data
{
    double evil_data;

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

And derive from both like this:

struct composed : public more_data, public vector_data
{
};

Will this destory the expected behaviour of operator[]? In other words, will the this-pointer of vector_data in the derived struct still point to the vector_data part of the struct, or will it point to the beginning of the derived struct?

If it does destroy operator[], then how can I resolve this problem? I can inherit from vector_data first, but suppose composed contains virtual functions. I know most compilers put the vtable at the end, but this is not guaranteed. What would be the best approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沦落红尘 2024-12-29 14:40:35

撇开不正确的指针算术问题不谈(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 指针。

Leaving aside the issues of your incorrect pointer arithmetics (the possibility of padding between x and y invalidates your assumption), here is a quick illustration of what's going on with this pointer when you use multiple inheritance:

#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();
}

showA and showB print different numbers; showC prints the same number as showA, because a is listed first in the list of bases. If you switch a and b there, then showC and showB would be the same. The "magic" is in the C++ compiler: it is smart enough to give each member function a correct this pointer.

又怨 2024-12-29 14:40:35

也许你想要的是这样的:

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

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

Probably what you want is something like:

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

   double& operator[](size_t index)
   {
       return data[index];
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文