C++类指针初始化
class Test
{
public:
void func(){cout << "hahaha" << endl;}
int get(){return a+b;}
Test():a(1),b(2){}
public:
int a,b;
};
而之后编译器会自动将这个类转换成:
class Test
{
int a,b;
};
void _test_func(Test * this);
int _test_get(Test* this);
........
类中的函数被编译器静态编译了,所有非虚函数(虚函数呢?别急,待会会解释到)都可以调用,因为函数地址编译期间已经确定。我们知道,类中的成员函数都是通过this指针调用成员变量的,编译器会将this指针作为默认参数传给类成员函数的,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
添加main函数如下:
int main()
{
Test *p=NULL;
p->func();//正确,没有调用成员变量,没有使用空的this指针
p->get();//错误,this指针为空,通过this指针调用变量所以出错
return 0;
}
运行结果如上,没有调用成员变量的func()函数正确执行,调用了成员变量的get()函数错误。两者其实都传入了空的this指针,前者没出错仅仅是因为没有调用this指针,而后者调用了。(此时p-func()和p->get()等同于func(NULL),get(NULL)......)是对象指针为NULL,而调用成员函数的时候,函数地址是编译期间确定的,成员函数不通过对象指针(也即当前的p指针)去调用,对象指针仅仅作为参数传入函数然后去调用成员变量。
好现在问题来了,如果是虚函数呢,因为虚函数要通过this指针计算vptr,然后找到vtable,然后dispatch。因为this指针为空,所以在找vtable时候就会coredump了。总之这类情况下,一切调用了this指针的函数都会出错,而完全不调用this指针的成员函数则没问题。
总结:任何时候定义指针的时候一定要初始化,这是良好的习惯,这个问题最初是由于当时写程序疏忽造成的,然而错有错着居然编译通过,所以当时一直没发现这个手误,现在追本溯源也算是对c++的内部机制有了更深的了解,不过也提示自己不能有侥幸心理,一定要养成良好的编程习惯,不管对于自己还是对于以后合作的伙伴都是一件好事。
C++类指针初始化的更多相关文章
- C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)
//多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...
- C#多态;父类引用指向子类对象;new和override的区别;new、abstract、virtual、override,sealed关键字区别和使用代码示例;c#类的初始化顺序
关于父类引用指向子类对象 例如: 有以下2个类 public class Father { public int age = 70; public static string name = " ...
- C++类构造函数初始化列表
C++类构造函数初始化列表 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample {public: ...
- c++类与初始化,const
--c++类与初始化,const --------------------------------2014/09/04 1. 类的定义(头文件.声明文件)看成类的外部接口,一般写成.h头文件. 2. ...
- C++类构造函数初始化列表(转)
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: { public: int a; float b; //构 ...
- jvm(2)类的初始化(二)和实例化
深入理解Java对象的创建过程:类的初始化与实例化 对象实例化内存分析: 对内存分配情况分析最常见的示例便是对象实例化: Object obj = new Object(); 这段代码的执行会涉及ja ...
- java类的初始化和构造函数
本人小白一枚,看java类的初始化的时候好晕的说,我觉着书上尽管说的对.但总认为有些信息没说出来,没说清楚,看了好多文章博客的,如今有些感悟,来小写下总结,也算是为以后再次复习种个好果子. 先摘一下书 ...
- C++ 静态成员的类内初始化
一般来说,关于C++类静态成员的初始化,并不会让人感到难以理解,但是提到C++ 静态成员的"类内初始化"那就容易迷糊了. 我们来看如下代码: //example.h #includ ...
- 为什么static成员必须在类外初始化,而不能在类的头文件中初始化
为什么static成员必须在类外初始化 为什么静态成员不能在类内初始化 在C++中,类的静态成员(static member)必须在类内声明,在类外初始化,像下面这样. class A { pri ...
随机推荐
- 需求管理是CMM可重复级中的6个关键过程域之一,其主要目标是__________。A.客观地验证需求管理活动
需求管理是CMM可重复级中的6个关键过程域之一,其主要目标是__________.A.客观地验证需求管理活动 需求管理是CMM可重复级中的6个关键过程域之一,其主要目标是_________ ...
- nginx实现防盗链
有时候在浏览网页的时候,会遇到某些文件(图片等)无法访问的情况,这是因为图片的所有方做了防盗链机制 了解防盗链之前先了解下http referer这个属性,http referer是请求头中的一部分, ...
- BZOJ1485: [HNOI2009]有趣的数列(Catalan数,质因数分解求组合数)
题意 挺简洁的. 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足a1<a3<…<a ...
- android 从contentView中删除view
1. ((ViewGroup)view.getParent()).removeView(view) 2. ViewGroup rootView = (ViewGroup) this.findViewB ...
- input禁止显示用户输入历史记录
input标签中加上属性autocomplete="off"
- ajax上传文件以及使用中常见问题处理
<script src="/scripts/ajaxfileupload.js"></script> <script src="/scrip ...
- Integer比较浅析
//Integer 型比较假如是使用 == ,只能比较数值为-128~127数值; 在这个范围内使用的是自动装箱拆箱: //.intValue()使用这个需要确认属性不为null; //equals( ...
- 闭包和OC的block的本质
“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域). http://blog.csdn ...
- 基本编程题 --python
1.让Python帮你随机选一个饮品吧! import random listC = ['加多宝', '雪碧', '可乐', '勇闯天涯', '椰子汁'] print(random.choices(l ...
- 第2节 azkaban调度:16、azkaban的介绍以及azkaban的soloserver的安装使用
2. 工作流调度器azkaban 2.1 概述 azkaban官网: https://azkaban.github.io/ 2.1.1为什么需要工作流调度系统 l 一个完整的数据分析系统通常都是由大 ...