首先我们应该了解指针的宽度,在32位系统中指针占4个字节,在64位系统中指针占8个字节。
有成员函数的对象占多少字节
#include <iostream>
using namespace std;
class father
{
public:
void speak()
{
cout << "父亲在说话" << endl;
}
};
void test()
{
father f1;
cout << "size = "<< sizeof(f1) << endl;
}
int main()
{
test();
system("pause");
return 0;
}
结果
size = 1
最后得出的结果是 1 字节。
成员函数不在对象上,而C++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存位置。
有虚函数的对象占多少字节
#include <iostream>
using namespace std;
class father
{
public:
virtual void speak()
{
cout << "父亲在说话" << endl;
}
};
void test()
{
father f1;
cout << "size = "<< sizeof(f1) << endl;
}
int main()
{
test();
system("pause");
return 0;
}
结果
size = 4
我这个是32位系统,最后得出的结果是 4 字节。(如果你们是64位系统,你们得出的结果是 8 字节)
为什么是4字节,因为现在的对象里面有了一个指针
而且不是普通的指针,专业名称 vfptr , v = virtual , f = function ,ptr = pointer。全称为虚函数指针,也可以叫做虚函数表指针,因为这个指针指向虚函数表,而虚函数表里存的就是虚函数地址。
重写
重写的满足条件
1,是继承关系
2,函数类型,函数名,参数列表要完全一样
#include <iostream>
using namespace std;
class father
{
public:
virtual void speak()
{
cout << "父亲在说话" << endl;
}
};
class son public:father
{
//public:
//void speak()
//{
//cout<<"儿子在说话"<<endl;
//}
};
void test()
{
son s1;
s1.speak();
cout<<sizeof(s1)<<endl;
}
int main()
{
test();
system("pause");
return 0;
}
得出的结果
父亲在说话
4
原因是子类继承父类,子类对象里也有虚函数指针,而且指向的虚函数表里存的是父类虚函数地址,所以调用的是父类的函数。
如果发生重写
#include <iostream>
using namespace std;
class father
{
public:
virtual void speak()
{
cout << "父亲在说话" << endl;
}
};
class son public:father
{
public:
void speak()
{
cout<<"儿子在说话"<<endl;
}
};
void test()
{
son s1;
s1.speak();
cout<<sizeof(s1)<<endl;
}
int main()
{
test();
system("pause");
return 0;
}
得出的结果
儿子在说话
4
原因是子类里的函数和父类的函数(子类写不写virtual关键字都一样,编译器默认是虚函数)满足重写的条件,发生了重写,此时子类虚函数指针指向虚函数表,而里面的地址被覆盖成了子类虚函数的地址,不再是父类的虚函数地址,所以此时调用的是子类的函数。