所以我知道int *知道取消引用4个字节而bool *知道取消引用1。
现在如果有一个班级:
Class rectangle {
Int l;
Int w;
};
现在知道矩形*是否取消引用8个字节?
如果是这样,现在假设有一个父类Shape和类矩形和从形状继承的圆。
Class circle {
Int r;
};
现在,如果我将Shape *指向一个矩形。如何知道取消引用8个字节而不是4个(圆圈)。
答案 0 :(得分:5)
对于一个对象,编译器知道类型,因此知道大小。
对于指针,编译器仍然知道类型,因此知道大小。
但是如果指针是一个子类......那么它仍然会使用基类!编译器没有丝毫想法,因为该内存中的内容不会在运行时到达那里。可能有1 shape
,可能有10亿shape
秒。它们可以是形状的子类,一些circle
和一些rectangle
s,以及一些MöbiusParallelograms
。它能做的最好的事情是取消引用shape
并切掉所有非shape
行为。
观察这里发生的事情:
#include <iostream>
class shape
{
};
class rectangle:public shape {
int l;
int w;
};
class circle:public shape {
int r;
};
int main()
{
shape s;
rectangle r;
circle c;
shape* sp;
std::cout << "Size of shape: " << sizeof(s) << std::endl;
std::cout << "Size of rectangle: " << sizeof(r) << std::endl;
std::cout << "Size of circle: " << sizeof(c) << std::endl;
sp = &s;
std::cout << "Size of dereferenced shape pointer pointing to shape: " << sizeof(*sp) << std::endl;
sp = &r;
std::cout << "Size of dereferenced shape pointer pointing to rectangle: " << sizeof(*sp) << std::endl;
sp = &c;
std::cout << "Size of dereferenced shape pointer pointing to circle: " << sizeof(*sp) << std::endl;
}
示例输出:
Size of shape: 1
Size of rectangle: 8
Size of circle: 4
Size of dereferenced shape pointer pointing to shape: 1
Size of dereferenced shape pointer pointing to rectangle: 1
Size of dereferenced shape pointer pointing to circle: 1
shape
Š!所有这些,shape
s!他们所有的个性都被剥夺了。
答案 1 :(得分:2)
现在,如果我
Shape*
指向rectangle
。如何解除引用8个字节而不是4个(circle
)。
编译器不知道如何做到这一点。如果您有一个Shape*
,它只知道Shape
,而不是关于派生类的任何内容。
一个众所周知的相关现象是object slicing。将派生类对象分配给基类对象时,会丢失基类对象中的派生类信息。
答案 2 :(得分:1)
每个指针都有一个类型;或者它指向的对象的类型。
编译器使用此类型信息来验证引用的成员(函数或数据成员)。从类型中,编译器可以计算出多少内存以进行干扰。
编辑1:
使用指向基类的指针时,编译器只知道基类项(成员和函数)。因此,取消引用基类指针可以访问基类中的项。
答案 3 :(得分:1)
有一个原因,您只能访问层次结构中类的已知成员。
'use strict';
//--- GET A REF TO CURRENT APP WITH STD ADDITONS ---
var app = Application.currentApplication()
app.includeStandardAdditions = true
var seApp = Application('System Events')
//--- Set the Clipboard so we can test for no selection ---
app.setTheClipboardTo("[NONE]")
//--- Activate the App to COPY the Selection ---
var safariApp = Application("Safari")
safariApp.activate()
delay(0.2) // adjust the delay as needed
//--- Issue the COPY Command ---
seApp.keystroke('c', { using: 'command down' }) // Press ⌘C
delay(0.2) // adjust the delay as needed
//--- Get the Text on the Clipboard ---
var clipStr = app.theClipboard()
console.log(clipStr)
//--- Display Alert if NO Selection was Made ---
if (clipStr === "[NONE]") {
var msgStr = "NO Selection was made"
console.log(msgStr)
app.activate()
app.displayAlert(msgStr)
}
答案 4 :(得分:1)
现在知道矩形*是否取消引用8个字节?
编译器可以访问完整类型的矩形,这意味着它知道它的布局可以计算变量的对齐方式。这是计算sizeof(矩形)所必需的,当你例如有一个指针pRectanle并且你用pRectangle + 1增加它时,会使用这个值。
如果你转发声明你的矩形类,那么编译器无法访问完整类型并且会产生编译错误,如果你使用任何需要完整类型的语言特性(即解除引用指针,继承自类,......)< / p>
现在,如果我将Shape *指向一个矩形。如何知道取消引用8个字节而不是4个(圆圈)。
我不确定我是否理解,例如:在这里Shape* pS = pRectangle;
,pS是静态类型Shape *所以当你增加这个指针或取消引用时,编译器只会看到静态类型Shape并使用它的大小。只有在使用pS调用虚拟方法时(如果有),才会使用动态类型。否则pS + 1将导致pS pt增加sizeof(Shape),如果pS指向某个数组,则不是你想要的。
答案 5 :(得分:1)
编译器不需要知道它取消引用的对象的大小。所有解除引用都会将值加载到指针中包含的地址。
当使用点(。)运算符引用结构或类的成员时,编译器从结构或类的开头获取指定偏移量处的值。
当使用箭头( - &gt;)运算符时,编译器将获取地址并将偏移量返回给所请求的元素。
当一个指针递增时,编译器将sizeof
对象添加到内存中的指针值,因为对象数组是连续的,我们现在指向下一个对象。
在C ++中,基类的元素存储在派生类的数据之前,因此向下转换或向上转换不会影响指针值。
在多重继承的情况下,强制转换为基类会使编译器返回派生类中基类对象的偏移量。这就是static_cast
和reinterpret_cast
可能返回不同值的原因。