C ++多重继承记忆体寻址问题 [英] C++ Multiple Inheritance Memory Addressing issue

查看:100
本文介绍了C ++多重继承记忆体寻址问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设正确完成操作,请忽略#include部分.同样,这可能是特定于实现的(但vtables的概念也是如此),但是我很好奇,因为它增强了我可视化多重继承的能力. (顺便说一下,我正在使用MinGW 4.4.0)

Please ignore the #include parts assuming they are done correctly. Also this could be implementation specific (but so is the concept of vtables) but i am just curious as it enhances me to visualize multiple inheritance. (I'm using MinGW 4.4.0 by the way)

初始代码:

class A {
public:
   A() : a(0) {}
   int a;
};

//Edit: adding this definition instead
void f(void* ptrA) {
   std::cout<<((A*)ptrA)->a;
}
//end of editing of original posted code

#if 0
//this was originally posted. Edited and replaced by the above f() definition
void f(A* ptrA) {
   std::cout<<ptrA->a;
}
#endif

这已编译并生成了目标代码.

this is compiled and Object code is generated.

在我使用的其他一些编译单元中(在包含上述代码的头文件之后):

in some other compilation unit i use (after inclusion of header file for above code):

class C : public B , public A {
public:
   int c;
}objC;

f(&objC); // ################## Label 1

objC的内存模型:

memory model for objC:

//<1> stuff from B
//<2> stuff from B
//<3> stuff from A : int a
//<4> stuff from C : int c

&objC在上面假定的内存模型中将包含< 1>的起始地址 编译器将如何/何时将其转换为< 3>?在检查Label 1的呼叫期间会发生这种情况吗?

&objC will contain starting address of <1> in memory model assumed above how/when will the compiler shift it to <3>? Does it happen during the inspection of call at Label 1 ?

:

因为Lable 1似乎是一个赠品,只是使编译器更加晦涩难懂.请参阅上面的已编辑代码".现在,编译器在何时何地执行操作?

since Lable 1 seems to be a give away, just making it a little more obscure for the compiler. Pls see the Edited code above. Now when does the compiler do and where?

推荐答案

简短答案:如果编译器知道基类与派生类之间的关系,则它将在强制转换操作期间调整指针值.

Short answer: Compiler will adjust pointer values during cast operations if it knows the relationship between the base and derived class.

让我们说您的类C的对象实例的地址为地址100.假设sizeof(C)==4.sizeof(B)和sizeof(A)也是如此.

Let's say the address of your object instance of class C was at address 100. And let's say sizeof(C) == 4. As does sizeof(B) and sizeof(A).

发生以下情况时发生投射:

When a cast happens such as the following:

C c;
A* pA = &c;  // implicit cast, preferred for upcasting
A* pA = (A*)&c; // explicit cast old style
A* pA = static_cast<A*>(&c); // static-cast, even better

pA的指针值将是c的内存地址加上从"A"在C处开始的偏移量.在这种情况下,假设sizeof(B)也是4,则pA将引用内存地址104.

The pointer value of pA will be the memory address of c plus the offset from where "A" begins in C. In this case, pA will reference memory address 104 assuming sizeof(B) is also 4.

所有这些都适用于将派生类指针传递到需要基类指针的函数中.隐式强制转换将与指针偏移调整一样发生.

All of this holds true for passing a derived class pointer into a function expecting a base class pointer. The implicit cast will occur as does the pointer offset adjustment.

同样,对于垂头丧气:

C* pC = (C*)(&a);

编译期间,编译器将负责调整指针值.

The compiler will take care of adjusting the pointer value during the assigment.

这一切的一个陷阱"是在没有完全声明的情况下向前声明一个类:

The one "gotcha" to all of this is when a class is forward declared without a full declaration:

 // foo.h
 class A;  // same as above, base class for C
 class C;  // same as above, derived class from A and B

 inline void foo(C* pC)
 {
      A* pA = (A*)pC; // oops, compiler doesn't know that C derives from A.  It won't adjust the pointer value during assigment
      SomeOtherFunction(pA); // bug! Function expecting A* parameter is getting garbage
 }

那是一个真正的错误!

我的一般规则.避免使用旧的"C样式"强制转换,而倾向于使用static_cast运算符,或者仅依靠隐式强制转换而不使用运算符来执行正确的操作(用于upcast).如果强制转换无效,则编译器将发出错误.

My general rule. Avoid the old "C-style" cast and favor using the static_cast operator or just rely on implicit casting without an operator to do the right thing (for upcasts). The compiler will issue an error if the casting isn't valid.

这篇关于C ++多重继承记忆体寻址问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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