c ++类及其布局和转换 [英] c++ Classes and their layouts and conversions

查看:50
本文介绍了c ++类及其布局和转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到了这段代码来测试我的cpp理解,我很困惑:



I was given this code to test my cpp understanding, and I am quite confused:

#include "stdafx.h"
#include <iostream>
#include <cstddef>

using namespace std;

class A
{
public:
    A() : m_x(0) { }

public:
    static ptrdiff_t member_offset(const A &a)
    {
        const char *p = reinterpret_cast<const char*>(&a);
        const char *q = reinterpret_cast<const char*>(&a.m_x);

        return q - p;
    }

private:
    int m_x;
};

class B
    : public A
{
public:
    B() : m_x('a') { }

public:
    static int m_n;

public:
    static ptrdiff_t member_offset(const B &b)
    {
        const char *p = reinterpret_cast<const char*>(&b);
        const char *q = reinterpret_cast<const char*>(&b.m_x);

        return q - p;
    }

private:
    char m_x;
};

int B::m_n = 1;

class C
{
public:
    C() : m_x(0) { }
    virtual ~C() { }

public:
    static ptrdiff_t member_offset(const C &c)
    {
        const char *p = reinterpret_cast<const char*>(&c);
        const char *q = reinterpret_cast<const char*>(&c.m_x);

        return q - p;
    }

private:
    int m_x;
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    B b;
    C c;
    std::cout << ((A::member_offset(a) == 0) ? 0 : 1);
    std::cout << ((B::member_offset(b) == 0) ? 0 : 2);
    std::cout << ((A::member_offset(b) == 0) ? 0 : 3);
    std::cout << ((C::member_offset(c) == 0) ? 0 : 4);
    std::cout << std::endl;

    return 0;
}





为什么答案为0204?



Why is the answer 0204?

推荐答案

在典型的实现中,答案是:



由于 A类没有任何虚函数,它都没有任何vtable,因为它不是从另一个类派生的,它的第一个成员将从与类本身相同的地址开始。这将为您提供输出的两个 0 0204 )。



由于 B类派生自 A类,其成员将被置于父级的成员之后布局中的类。由于类A 不为空,因此偏移量不会为0.如果它为空,则可能为0(取决于编译器)。这将在您的输出中给出 2



对于 C类,vtable可以放在数据之前,因此数据不会偏移0.这将在输出中给出 4



这大部分是编译器和平台相关的,可以根据所选的编译器选项(对齐,空类优化......)而变化。



顺便说一句,你应该尽可能避免依赖于类布局的代码,因为它不可移植。
On a typical implementation, the answer would be:

Since class A does not have any virtual functions, it will not have any vtable and since it does not derive from another class it first member will start at the same address as the class itself. This will give you the two 0 of your output (0204).

Since class B derives from class A, its members will be placed after those of the parent class in the layout. And since class A is not empty, then the offset will not be 0. It might have been 0 (depending on the compiler) if it was empty. This will give the 2 in your output.

For class C, the vtable could be placed before the data thus the data won''t be at offset 0. This will give the 4 in your output.

Most of this is compiler and platform dependant and can vary depending according to selected compiler options (alignment, empty class optimization...)

By the way, you should avoid code that depends on the layout of a class whenever possible as it will not be portable.


这篇关于c ++类及其布局和转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆