题目(六):运行下列C++代码,输出什么?
struct Point3D
{
int x;
int y;
int z;
};
int _tmain(int argc, _TCHAR* argv[])
{
Point3D* pPoint = NULL;
int offset = (int)(&(pPoint)->z);
printf("%d", offset);
return 0;
}
输出结果为8。pPoint地址为0,然后&((pPoint)->z)只是做了去地址操作,返回的是z在结构体中的地址
题目(七):运行下列C++代码,输出什么?
class A
{
public:
A()
{
Print();
}
virtual void Print()
{
printf("A is constructed.\n");
}
};
class B: public A
{
public:
B()
{
Print();
}
virtual void Print()
{
printf("B is constructed.\n");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* pA = new B();
delete pA;
return 0;
}
输出
A is constructed.
B is constructed.
因为B继承A,所以先初始化A,在初始化B,A虽然有虚函数但是还是输出A的print,然后B输出B的
题目(九):在C++中,struct和class有什么不同?
struct其实作用和class类似,但是默认情况下,如果没有标明函数或遍历的权限的情况下,struct中为public,而class中为private
题目(一):我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量)。请问:能不能同时用static和const修饰类的成员函数?
不明白题目什么意思:
答案如下:
分析:答案是不可以。C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时static的用法和static是冲突的。
我们也可以这样理解:两者的语意是矛盾的。static的作用是表示该函数只作用在类型的静态变量上,与类的实例没有关系;而const的作用是确保函数不能修改类的实例的状态,与类型的静态变量没有关系。因此不能同时用它们。题目(二):运行下面的代码,输出是什么?
class A
{
};
class B
{
public:
B() {}
~B() {}
};
class C
{
public:
C() {}
virtual ~C() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
printf("%d, %d, %d\n", sizeof(A), sizeof(B), sizeof(C));
return 0;
}
这道题目出的很好,自己也忘掉这种情况了,下面为网络上面的解释,感觉很不错
首先需要明白
程序运行过程中,所用到的存储结构
代码区:存储程序的代码
数据区:数据区存放全局变量和静态变量,与常量 其实可以细化为全局/静态数据区与常量数据区
堆区:动态分配使用的。
栈区:存放局部变量与传来的参数
类在内存里的数据连续存储,基本上就是存几个非静态成员变量与虚函数表指针(如果存在)
然后需要明白sizeof这个操作符的作用范围
“The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand.”,而类中的函数代码在“代码区”,所以sizeof返回的A类型的对象占用的内存空间不包括函数。
The sizeof operator cannot be used with the following operands:
Functions. (However, sizeof can be applied to pointers to functions.)
Bit fields.
Undefined classes.
The type void.
Dynamically allocated arrays.
External arrays.
Incomplete types.
Parenthesized names of incomplete types.
最后还有一个解释很合理,很准确
类里面占空间的是成员变量,如果有虚函数的话,编译器会插入虚表指针,也占空间,如果由纯虚基类的话,看编译器的实现,可能会比+基类大,也可能会小。此外还要考虑内存对齐所浪费的空间。
ps:如果类为空,或由纯虚空基类派生出的空类的话,编译器可能会做调整,使其大小不是0.
海涛博客里的答案
分析:答案是1, 1, 4。class A是一个空类型,它的实例不包含任何信息,本来求sizeof应该是0。但当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占用多少内存,由编译器决定。Visual Studio 2008中每个空类型的实例占用一个byte的空间。
class B在class A的基础上添加了构造函数和析构函数。由于构造函数和析构函数的调用与类型的实例无关(调用它们只需要知道函数地址即可),在它的实例中不需要增加任何信息。所以sizeof(B)和sizeof(A)一样,在Visual Studio 2008中都是1。
class C在class B的基础上把析构函数标注为虚拟函数。C++的编译器一旦发现一个类型中有虚拟函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针。在32位的机器上,一个指针占4个字节的空间,因此sizeof(C)是4。
总结来说:一个空类的空间大小虽然实际上为0,但是编译器会优化,至于多少没有一个准确的结构
sizeof计算的是所指对象占用的空间,而类里面的函数代码完全在代码区,不占对象的空间
虚函数 在类中会隐含一个虚函数指针,占用空间为4字节,当然在空类中有虚函数就有空间,不必优化
题目(三):运行下面中的代码,得到的结果是什么?
class A
{
private:
int m_value;
public:
A(int value)
{
m_value = value;
}
void Print1()
{
printf("hello world");
}
void Print2()
{
printf("%d", m_value);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* pA = NULL;
pA->Print1();
pA->Print2();
return 0;
}
这一题海涛接的十分好,因为 print1是函数,不占用类对象的空间,此时类对象为空,虽然使用print1函数,但是没有访问不能访问的空间正确输出
但是pa->print2()就出错 因为使用了类对象,即this指针指向的m_value,没有空间,当然访存越界。
题目(五):静态成员函数能不能同时也是虚函数?
不能:
静态成员函数,不需通过this,即实际存在的对象来调用
虚函数,必须要通过实际存在的对象来调用,这两个不能混
海涛答案:
分析:答案是不能。调用静态成员函数不要实例。但调用虚函数需要从一个实例中指向虚函数表的指针以得到函数的地址,因此调用虚函数需要一个实例。两者相互矛盾。
出处http://zhedahht.blog.163.com/。