1.
类A,A的结构任意。
#include <iostream>
#include <string>
calss A
{
……
};
类D,D中有一成员函数,它没有操作任何成员数据。
class D
{
public:
void show()
{
std::cout << "this's D" << std::endl;
}
};
main中,将一个A的实例强制转换为D
A a;
void* p_t = &a;
D* p_d = (D*)p_t;
然后调用D的成员函数
p_d->show();
运行,此种情况下编译器和运行时均不报错,运行结果正常。
2.
向类D增加静态变量
static int s_num;
static string s_name;
在全局中初始化静态变量。(类的静态变量不能在类内部初始化,应该在全局作用域内,以ClassName::para的形式初始化。)
class D
{
……
}
int D::num = 1234;
string name = "CLASS_D";
修改类D的show()方法
void show()
{
std::cout << "this's D. " << std::endl;
std::cout << "the static number is " << s_num << std::endl;
std::cout << "the static string is " << s_name << std::endl;
}
此种情况下编译器和运行时也不会报错,运行结果也正确。
3.
向类D增加非静态的成员变量
int num ;
在D的构造函数中初始化num
D(void)
{
num = 1000;
}
类D的show()方法增加一行
std::cout << "the number is " << num << std::endl;
再次运行。
编译器和运行时仍然不报错,但结果num的值是错误的。
结论
编译器和运行时允许程序员将某块内存区域强制转换为某类型的实例,并可使用该实例访问类中没有操纵非静态成员数据的方法(该方法没有操纵成员数据,或是操纵的成员数据是静态数据),返回正确结果。
类中没有操纵非静态成员数据的方法包括了:类的静态函数;类的普通非static的并且函数中未使用未修改类的非静态数据的成员函数。
原因分析:
静态变量存放在全局的公共区域,类的非虚的成员函数也存放在公共区域。
类的一个实例在内存中占用的区域包含的数据有:类的非静态成员数据;如果类有虚函数,则有一个虚函数列表。
若某成员函数没有访问非静态变量,调用这个非虚的成员函数只需要访问公共区域(静态变量和非虚函数都在公共区域)。它不需要访问这个类的实例所占的内存区域,也就不会要求这块内存区域是否符合该类的数据格式。函数执行的结果也一定是正确的。
若该成员函数访问了非静态变量,程序会强行按照类的数据格式来解析这段区域,里面的数据自然是错的。
若成员函数是一个虚函数的情况,可推理并验证。-_-b
扩展:
若void* p_t并不指向某其他类型的区域,而是NULL。——可推理并验证。-_-b