上面的代码会打印“A”。
C++ 类指针定义的时候没有初始化的时候,居然可以安全的调用类内部的成员函数而不出错。
在网上查了一下:
 
初始化为NULL的类指针可以安全的调用不涉及类成员变量的类成员函数而不出错,但是如果类成员函数中调用了类成员变量则会出错,既然赋值为NULL的情况都可以使用,那么自然不初始化的类指针同样满足这类情况。
 
假设现在有一个简单的类定义如下:
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++类指针初始化的更多相关文章

  1. C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)

    //多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...

  2. C#多态;父类引用指向子类对象;new和override的区别;new、abstract、virtual、override,sealed关键字区别和使用代码示例;c#类的初始化顺序

    关于父类引用指向子类对象 例如: 有以下2个类 public class Father { public int age = 70; public static string name = " ...

  3. C++类构造函数初始化列表

    C++类构造函数初始化列表 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample {public:     ...

  4. c++类与初始化,const

    --c++类与初始化,const --------------------------------2014/09/04 1. 类的定义(头文件.声明文件)看成类的外部接口,一般写成.h头文件. 2. ...

  5. C++类构造函数初始化列表(转)

    构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: { public:     int a;     float b;     //构 ...

  6. jvm(2)类的初始化(二)和实例化

    深入理解Java对象的创建过程:类的初始化与实例化 对象实例化内存分析: 对内存分配情况分析最常见的示例便是对象实例化: Object obj = new Object(); 这段代码的执行会涉及ja ...

  7. java类的初始化和构造函数

    本人小白一枚,看java类的初始化的时候好晕的说,我觉着书上尽管说的对.但总认为有些信息没说出来,没说清楚,看了好多文章博客的,如今有些感悟,来小写下总结,也算是为以后再次复习种个好果子. 先摘一下书 ...

  8. C++ 静态成员的类内初始化

    一般来说,关于C++类静态成员的初始化,并不会让人感到难以理解,但是提到C++ 静态成员的"类内初始化"那就容易迷糊了. 我们来看如下代码: //example.h #includ ...

  9. 为什么static成员必须在类外初始化,而不能在类的头文件中初始化

    为什么static成员必须在类外初始化 为什么静态成员不能在类内初始化 在C++中,类的静态成员(static member)必须在类内声明,在类外初始化,像下面这样.   class A { pri ...

随机推荐

  1. nodejs 生成验证码

    此方法需要nodejs 安装canvas 扩展 准备工作 以Linux为例 1.服务器gcc版本需4.8以上 2.安装所需扩展 yum install cairo cairo-devel cairom ...

  2. react 父子传值

    import React from 'react'; import ReactDOM from 'react-dom'; import $ from 'jquery'; //var $ = requi ...

  3. phpMyAdmin 缺少 mcrypt 扩展.请检查 PHP 配置.

    原文链接:http://zhidao.baidu.com/link?url=5Y4eT7bcnTHFUtzDMs7mvtsGc7jqbs2yqXG06AP5_6t7wukC7uVozSrbUf7iYl ...

  4. 一本通 1434:【例题2】Best Cow Fences

    Best Cow Fences 二分答案 + 前缀和 个人认为题意没有表述清楚,本题要求的是满足题意的连续子序列(难度大大降低了有木有). 本题的精度也是非常令人陶醉,请您自行体会吧! #includ ...

  5. How many '1's are there题解

    Description: Description: 第一行输入数字n(n<=50),表示有n组测试用例,第2到第n+1行每行输入数m(m为整数),统计并输出m用二进制表示时,1的个数. 例如:m ...

  6. 自定义消息中如果需要定义WPARAM和LPARAM,该怎么使用和分配?

    写Windows程序不可避免要使用自定义的消息,也就是从WM_USER开始定义的消息.在定义一个消息后,往往我们还要定义针对该消息的WPARAM甚至是LPARAM.WPARAM和LPARAM是什么,可 ...

  7. [转+补]Android打包so后魅族5中安装运行崩溃问题的解决方法

    上周在做噪音检测so集成中,遇到不同的so库打包到 APK 时,安装在某些机器上,出现 java.lang.UnsatisfiedLinkError 加载失败. 为此,深究了一下原理,和给出了解决方案 ...

  8. KVC/KVO 本质

    KVO 的实现原理 KVO是关于runtime机制实现的 当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法.派生类 ...

  9. EJB2.0版本的HelloWorld

    EJB2.0版本的HelloWorld   虽然EJB3.1已经出来了,可是EJB2.0的项目还需要维护啊.下面写个简单EJB2.0的HelloWorld程序,练练手.   环境: JBoss 4.0 ...

  10. 自学Spring Boot

    简介: Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配 ...