“类名称”+“::”调用方式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“类名称”+“::”调用方式相关的知识,希望对你有一定的参考价值。
注:
对静态函数或静态成员的调用方式不做分析;
以下提到的测试环境为vc6.0;
调试程序时看到这样的代码:
1 pObj->ClassName::Function();
开始不理解为什么要在“->”后加上类名“ClassName::”,一般使用中类名称加“::”(ClassName::)是用来调用静态函数或静态成员的,带着疑问做了下尝试。
定义类A:
1 class A 2 { 3 public: 4 void Test() 5 { 6 int nVal= 8; 7 int nVal1 = nVal; 8 } 9 10 };
调用方式:
1 A* pA = NULL; 2 pA->A::Test();
测试能够顺利通过。但是调试时进入A类的Test()函数发现this指针为空:
修改类A为:
1 class A 2 { 3 public: 4 A(){ m_nVal = 5; } 5 ~A(){} 6 7 void Test() 8 { 9 int nVal= 8; 10 int nVal1 = nVal; 11 int nVal2 = m_nVal; //调用成员变量 12 13 } 14 15 protected: 16 int m_nVal; //增加成员变量 17 18 };
再次执行:
1 A* pA = NULL; 2 pA->A::Test();
这次程序会崩溃,调试发现是在使用成员变量时崩溃,如下图:
通过上面的测试初步得出结论,当采用pA->A::Test()这种方式进行调用时,如果Test()函数中没有使用类的非静态成员变量,调用的指针(具体的类对象指针this)是否为空可以不考虑,能够顺利通过,如果Test()函数中使用了类的非静态成员变量,则必须要求调用的指针不为null,也就是必须有已分配了内存空间的类对象,因为这些非静态成员变量的空间是分配在类对象上的。对于类的静态成员这里就不在叙述(因为类的静态成员属于类本身,不属于类对象)。
到这里问题就来了,调用时直接写成pA->Test()不就可以了,干嘛写的这么别扭,给人感觉很深奥的样子(事实是有点深奥),通过经验猜测应该和继承有关系,于是做了如下尝试:
修改类A:
1 class A 2 { 3 public: 4 A(){ m_nVal = 5; } 5 ~A(){} 6 7 virtual void Test() //变为虚函数 8 { 9 int nVal= 8; 10 int nVal1 = nVal; 11 int nVal2 = m_nVal; 12 } 13 14 protected: 15 int m_nVal; 16 };
增加类B继承于类A:
1 class A 2 { 3 public: 4 A(){ m_nVal = 5; } 5 ~A(){} 6 7 virtual void Test() //变为虚函数 8 { 9 int nVal= 8; 10 int nVal1 = nVal; 11 int nVal2 = m_nVal; 12 } 13 14 protected: 15 int m_nVal; 16 };
调用方式:
A* pA = new B;
pA->Test(); //第一步
pA->A::Test(); //第二步
调试时发现,当执行第一步时进入的是类B(子类)中定义的Test()函数,执行第二步时进入的是类A(父类)中的Test()函数,第一步调用是实现多态的一种方式很常见,而第二种调用方式是刻意破坏多态的结构,已达到指定的去执行父类的函数,我个人不赞成这种写法,首先它打破了常规写法,并且看起来不易理解,也不利于维护扩展,完全可以采取其他常见方式实现相应功能。
以上是关于“类名称”+“::”调用方式的主要内容,如果未能解决你的问题,请参考以下文章