精华内容
下载资源
问答
  • 在C++中,如果某个类的成员函数中使用了该类的成员(成员变量或成员函数),则该成员函数会通过一个名为this的隐式参数来访问这个成员(成员变量或成员函数)。 例如,有一个类 classmyClass() { public: intm_i...

    在C++中,如果某个类的成员函数中使用了该类的成员(成员变量或成员函数),则该成员函数会通过一个名为this的隐式参数来访问这个成员(成员变量或成员函数)。

    例如,有一个类

    class myClass() {
    public:
      int m_i;
      int getI() {
         return m_i;
      }
    }

    其中,成员函数getI()中使用了该类的成员变量m_i,因此getI()函数实际上包含了一个隐藏的参数this,

    int getI(this){
       return this->m_i;
    }

    接下来分别定义myClass类的两个对象,并分别这两个对象的m_i成员变量进行赋值:

    myClass A1;
    A1.m_i = 1;
    myClass A2;
    A2.m_i = 2;

    此时,对于A1.getI()函数,编译器会将A1的地址作为this参数传递给getI(),因此A1.getI()函数的返回值是1;而,对于A2.getI()函数,编译器会将A2的地址作为this参数传递给getI(),因此A2.getI()函数的返回值是2。

    展开全文
  • c++成员函数默认参数

    千次阅读 2015-04-17 10:44:57
    c++成员函数默认参数 多文件编写注意.h file#ifndef PARAMETER_H_ #define PARAMETER_H_class cabc { private: char m_abc; static int def; public: //error: invalid use of non-static data member 'cabc::m_...

    在C++中,可以为参数指定默认值。在函数调用时没有指定与形参相对应的实参时, 就自动使用默认参数。

    默认参数的语法与使用:
    (1)在【函数声明】【定义】时,直接对参数赋值。这就是默认参数的两种方式;
    但应该尽量在声明是定义默认参数【.h文件】这是给外部的借口。
    或者有特殊要求,才在【.cpp文件】中定义
    (2)在函数调用时,省略部分或全部参数。这时可以用默认参数来代替。
    (3)默认参数应该从右向左
    (4)需要注意虚函数,多态时候,default parametrs 问题,默认参数并不会“多态”。
    编译期决定??

    注意:
    (1)默认参数只可在函数声明中设定一次。只有在没有函数声明时,才可以在函数定义中设定。(此句意为存在函数声明和定义两部分的时候。 定义或者声明只有一处)
    (2)注意函数重载,防止二义性
    c++成员函数默认参数 多文件编写注意

    .h file

    #ifndef  PARAMETER_H_
    #define  PARAMETER_H_
    
    class cabc
    {
    private:
        char m_abc;
        static int def;
    public:
        //error: invalid use of non-static data member 'cabc::m_abc'
        //void print(char a=m_abc,char* str) const; //error
    
        //void print(int a=5);
        void print(char* str1,char* str=NULL);
        void print(int i=def) const;
        int add(int i=def);
        cabc(char c='a');
        int set_value(int i);
        ~cabc();
    };
    
    #endif 

    .cpp file

    
    #include <iostream>
    #include "parameters.h"
    using std::cout;
    using std::endl;
    
    int cabc::def=100;
    //缺省参数放在声明写
    //ERROR:like the followed
    /*void cabc::print(char a,char*) const //error
    {
        cout<<"m_abc="<<m_abc<<endl;
    }*/
    
    //error: 'def' was not declared in this scope
    //error: non-member function 'void print(int)' cannot have cv-qualifier 
    //void print(int i=def) const   //error
    
    
    //after previous specification in 'void def::print(int)'
    //void def::print(int a=100)
    //{
    //  cout<<"a= "<<a<<endl;
    //}
    
    void cabc::print(int i) const
    {
        cout<<"def="<<def<<endl;
    }
    int cabc::add(int i)
    {
        return ++i;
    }
    int cabc::set_value(int i=1)
    {
        return def=i;
    }
    void cabc::print(char* str1,char* str)
    {
        cout<<"str= "<<str<<endl;
        printf("\n");
        printf("str: %p\n",str);
    }
    
    cabc::cabc(char c):m_abc(c)
    {
        cout<<"cabc's constructor\n";
    }
    cabc::~cabc()
    {
        cout<<"cabc's destructor\n";
    }
    
    
    
    int main()
    {
        cabc c1;
        char str[]="abc";
        //c1.print(str);
        c1.print();
        cout<<"num= "<<c1.add()<<endl;
        cout<<"c1.set_value()= "<<c1.set_value()<<endl;
        c1.print();
        c1.print((char*)NULL);
    }
    
    #include <iostream>
    using namespace std;
    
    class  Root
    {
    public :
      virtual void print(int arg=11)
      {
        cout<<"Root\n";
        cout<<arg<<endl;
      } 
      // do something
    };
    
    class  RootDerived :  public  Root
    {
    public :
      // overwrit the function ,the default argument will be problematic
      virtual void  print(int arg=33)
      {
        cout<<"RootDerived\n";
        cout<<arg<<endl;
      } 
      // do something
    };
    
    int  main()
    {
      Root *pr = new  RootDerived;
      pr-> print();
      // do something
    }
    展开全文
  • C++成员函数 this指针 调用约定

    千次阅读 2013-10-07 00:05:17
    关键字:C++成员函数 this指针 调用约定 一、成员函数指针的用法  在C++中,成员函数的指针是个比较特殊的东西。对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用。但对成员函数来说,...

    摘要:介绍了如何取成员函数的地址以及调用该地址.

    关键字:C++成员函数 this指针 调用约定


    一、成员函数指针的用法

      在C++中,成员函数的指针是个比较特殊的东西。对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用。但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法。C++专门为成员指针准备了三个运算符: "::*"用于指针的声明,而"->*"和".*"用来调用指针指向的函数。比如:

       class tt

       {

           public: void foo(int x){ printf("\n %d \n",x); }

       };

     

       typedef   void  ( tt::* FUNCTYPE)(int );

     

     

        FUNCTYPE ptr = tt::foo;  //给一个成员函数指针赋值.

     

        tt a;

        (a.*ptr)(5);   //调用成员函数指针.

     

        tt *b = new tt;

        (b->*ptr)(6);  //调用成员函数指针.


      注意调用函数指针时括号的用法,因为 .* 和 ->* 的优先级比较低,必须把它们和两边要结合的元素放到一个括号里面,否则通不过编译。不仅如此,更重要的是,无法为成员函数指针进行任何的类型转换,比如你想将一个成员函数的地址保存到一个整数中(就是取类成员函数的地址),按照一般的类型转换方法是办不到的.下面的代码:

        DWORD dwFooAddrPtr= 0;

        dwFooAddrPtr = (DWORD) &tt::foo;  /* Error C2440 */

        dwFooAddrPtr = reinterpret_cast (&tt::foo); /* Error C2440 */

      你得到只是两个c2440错误而已。当然你也无法将成员函数类型转换为其它任何稍有不同的类型,简单的说,每个成员函数指针都是一个独有的类型,无法转换到任何其它类型。即使两个类的定义完全相同也不能在其对应成员函数指针之间做转换。这有点类似于结构体的类型,每个结构体都是唯一的类型,但不同的是,结构体指针的类型是可以强制转换的。有了这些特殊的用法和严格的限制之后,类成员函数的指针实际上是变得没什么用了。这就是我们平常基本看不到代码里有"::*", ".*" 和 "->*"的原因。

    二、取成员函数的地址

      当然,引用某位大师的话:"在windows中,我们总是有办法的"。同样,在C++中,我们也总是有办法的。这个问题,解决办法已经存在了多年,并且广为使用(在MFC中就使用了)。一般有两个方法,一是使用内嵌的汇编语言直接取函数地址,二是使用union类型来逃避C++的类型转换检测。两种方法都是利用了某种机制逃避C++的类型转换检测,为什么C++编译器干脆不直接放开这个限制,一切让程序员自己作主呢?当然是有原因的,因为类成员函数和普通函数还是有区别的,允许转换后,很容易出错,这个在后面会有详细的说明。现在先看看取类成员函数地址的两种方法:

    第一种方法:

    template

    void GetMemberFuncAddr_VC6(ToType& addr,FromType f)

    {

        union

        {

           FromType _f;

           ToType   _t;

        }ut;

     

        ut._f = f;

     

        addr = ut._t;

    }


    这样使用:

    DWORD dwAddrPtr;

    GetMemberFuncAddr_VC6(dwAddrPtr,&tt::foo);

      为什么使用模版? 呵呵,如果不使用模版,第二个参数该怎么些,写成函数指针且不说太繁琐,关键是没有通用性,每个成员函数都要单独写一个转换函数。


    第二种方法:

    #define GetMemberFuncAddr_VC8(FuncAddr,FuncType)\

    {                                               \

        __asm                                       \

        {                                           \

            mov eax,offset FuncType                 \

        };                                          \

        __asm                                       \

        {                                           \

            mov FuncAddr, eax                       \

        };                                          \

    }

     

    这样使用:

    DWORD dwAddrPtr;

    GetMemberFuncAddr_VC8(dwAddrPtr,&tt::foo);

      本来是想写成一个模版函数的,可惜虽然通过了编译,却不能正确运行。估计在汇编代码中使用模版参数不太管用,用offset取偏移量直接就得0。

      上面的宏是可以正确运行的,并且还有一个额外的好处,就是可以直接取私有成员函数的地址(大概在asm括号中,编译器不再检查代码的可访问性)。不过缺点是它在vc6下是无法通过编译的,只能在VC8下使用。

    三、调用成员函数地址

      通过上面两个方法,我们可以取到成员函数的地址。不过,如果不能通过地址来调用成员函数的话,那也还是没有任何用处。当然,这是可行的。不过在这之前,需要了解关于成员函数的一些知识。
      我们知道,成员函数和普通函数最大的区别就是成员函数包含一个隐藏的参数this指针,用来表明成员函数当前作用在那一个对象实例上。根据调用约定(Calling Convention)的不同,成员函数实现this指针的方式也不同。如果使用__thiscall调用约定,那么this指针保存在寄存器ECX中,VC编译器缺省情况下就是这样的。如果是__stdcall或__cdecl调用约定,this指针将通过栈进行传递,且this指针是最后一个被压入栈的参数,相当于编译器在函数的参数列表中最左边增加了一个this参数。
      这里还有件事不得不提,虽然vc将__thiscall类型作为成员函数的默认类型,但是vc6却没有定义__thiscall关键字!如果你使用__thiscall来定义一个函数,编译器报错:'__thiscall' keyword reserved for future use。

    知道这些就好办了,我们只要根据不同的调用约定,准备好this指针,然后象普通函数指针一样的使用成员函数地址就可以了。

      对__thiscall类型的成员函数(注意,这个是VC的默认类型),我们在调用之前加一句: mov ecx, this; 然后就可以调用成员函数指针。例如:

    class tt

    {

     public:

     

        void foo(int x,char c,char *s)//没有指定类型,默认是__thiscall.

        {

            printf("\n m_a=%d, %d,%c,%s\n",m_a,x,c,s);

        }

     

        int m_a;

    };

     

    typedef  void (__stdcall *FUNCTYPE)(int x,char c,char *s);//定义对应的非成员函数指针类型,注意指定__stdcall.

     

     

        tt abc;

        abc.m_a = 123;

     

        DWORD ptr;

        DWORD This = (DWORD)&abc;

     

        GetMemberFuncAddr_VC6(ptr,tt::foo); //取成员函数地址.

     

        FUNCTYPE fnFooPtr  = (FUNCTYPE) ptr;//将函数地址转化为普通函数的指针.

     

        __asm //准备this指针.

        {

            mov ecx, This;

        }

     

        fnFooPtr(5,'a',"7xyz"); //象普通函数一样调用成员函数的地址.


      对其它类型的成员函数,我们只要申明一个与原成员函数定义完全类似的普通函数指针,但在参数中最左边加一个void * 参数。代码如下:

    class tt

    {

     

    public:

     

        void __stdcall foo(int x,char c,char *s)//成员函数指定了__stdcall调用约定.

        {

            printf("\n m_a=%d, %d,%c,%s\n",m_a,x,c,s);

        }

     

        int m_a;

    };

     

    typedef  void (__stdcall *FUNCTYPE)(void *This,int x,char c,char *s);//注意多了一个void *参数.

     

        tt abc;

        abc.m_a = 123;

     

        DWORD ptr;

     

        GetMemberFuncAddr_VC6(ptr,tt::foo); //取成员函数地址.

     

        FUNCTYPE fnFooPtr = (FUNCTYPE) ptr;//将函数地址转化为普通函数的指针.

     

        fnFooPtr(&abc,5,'a',"7xyz"); //象普通函数一样调用成员函数的地址,注意第一个参数是this指针.

      每次都定义一个函数类型并且进行一次强制转化,这个事是比较烦的,能不能将这些操作写成一个函数,然后每次调用是指定函数地址和参数就可以了呢?当然是可以的,并且我已经写了一个这样的函数。

    //调用类成员函数

    //callflag:成员函数调用约定类型,0--thiscall,非0--其它类型.

    //funcaddr:成员函数地址.

    //This:类对象的地址.

    //count:成员函数参数个数.

    //...:成员函数的参数列表.

    DWORD CallMemberFunc(int callflag,DWORD funcaddr,void *This,int count,...)

    {

           DWORD re;

     

           if(count>0)//有参数,将参数压入栈.

           {

                  __asm

                  {

                        mov  ecx,count;//参数个数,ecx,循环计数器.

                        mov  edx,ecx;

                        shl  edx,2;   

                        add  edx,0x14;  edx = count*4+0x14;

     

             next:      push  dword ptr[ebp+edx];

                        sub   edx,0x4;

                        dec   ecx 

                        jnz   next;

                  }

           }

     

           //处理this指针.

           if(callflag==0) //__thiscall,vc默认的成员函数调用类型.

           {

                  __asm mov ecx,This;

           }

           else//__stdcall

           {

                  __asm push This;

           }

     

           __asm//调用函数

           {

                  call funcaddr;

                  mov  re,eax;

           }

     

           return re;

    }

    使用这个函数,则上面的两个调用可以这样写:

    CallMemberFunc(0,ptr1,&abc,3,5,'a',"7xyz");//第一个参数0,表示采用__thiscall调用.

    CallMemberFunc(1,ptr2,&abc,3,5,'a',"7xyz");//第一个参数1,表示采用非__thiscall调用
    .

      需要说明的是,CallMemberFunc是有很多限制的,它并不能对所有的情况都产生正确的调用序列。原因之一是它假定每个参数都使用了4个字节的栈空间。这在大多数情况下是正确的,比如参数为指针,char,short,int,long以及对应的无符号类型,这些参数确实都是每一个参数使用了4字节的栈空间。但是还有很多情况下,参数不使用4字栈空间,比如double,自定义的结构或类.float虽然是占了4字节,但编译器还产生了一些浮点指令,而这些无法在CallMemberFunc被模拟出来,因此对float参数也是不行的。

      总结一下,如果成员函数的参数都是整型兼容类型,则可以使用CallMemberFunc调用函数地址。如果不是,那就只有按前面的方法,先定义对应的普通函数类型,强制转化,准备this指针,然后调用普通函数指针。

    四、进一步的讨论

      到目前为止,已经讨论了如何取成员函数的地址,然后如何使用这个地址。但是还有些重要的情况没有讨论,我们知道成员函数可分为三种:普通成员函数,静态,虚拟。另外更重要的是,在继承甚至多继承下情况如何。

    首先看看最简单的单继承,非虚拟函数的情况。
     

    class tt1

    {

    public:

           void foo1(){ printf("\n hi, i am in tt1::foo1\n"); }

    };

     

    class tt2 : public tt1

    {

    public:

           void foo2(){ printf("\n hi, i am in tt2::foo2\n"); }

    };

    注意,tt2中没有定义函数foo1,它的foo1函数是从tt1中继承过来的。这种情况下,我们直接取tt2::foo1的地址行会发生什么?

    DWORD tt2_foo1;

    tt1 x;

     

    GetMemberFuncAddr_VC6(tt2_foo1,&tt2::foo1);

    CallMemberFunc(0,tt2_foo1,&x,0); // tt2::foo1 = tt1::foo1

      运行结果表明,一切正常!当我们写下tt2::foo1的时候,编译器知道那实际上是tt1::foo1,因此它会暗中作替换。编译器(VC6)产生的代码如下:

    GetMemberFuncAddr_VC6(tt2_foo1,&tt2::foo1); //源代码.

     

    //VC6编译器产生的汇编代码:

     

    push offset @ILT+235(tt1::foo1) (004010f0) //直接用tt1::foo1 替换 tt2::foo1.

    ...

    再看看稍微复杂些的情况,继承情况下的虚拟函数。

    class tt1

    {

    public:

           void foo1(){ printf("\n hi, i am in tt1::foo1\n"); }

           virtual void foo3(){ printf("\n hi, i am in tt1::foo3\n"); }

    };

     

    class tt2 : public tt1

    {

    public:

           void foo2(){ printf("\n hi, i am in tt2::foo2\n"); }

           virtual void foo3(){ printf("\n hi, i am in tt2::foo3\n"); }

    };

    现在tt1和tt2都定义了虚函数foo3,按C++语法,如果通过指针调用foo3,应该发生多态行为。下面的代码:

    DWORD tt1_foo3,tt2_foo3;

     

    GetMemberFuncAddr_VC6(tt1_foo3,&tt1::foo3);

    GetMemberFuncAddr_VC6(tt2_foo3,&tt2::foo3);

     

    tt1 x;

    tt2 y;

     

    CallMemberFunc(0,tt1_foo3,&x,0); // tt1::foo3

    CallMemberFunc(0,tt2_foo3,&x,0); // tt2::foo3

     

    CallMemberFunc(0,tt1_foo3,&y,0); // tt1::foo3

    CallMemberFunc(0,tt2_foo3,&y,0); // tt2::foo3

    输出如下:

    hi, i am in tt1::foo3

    hi, i am in tt1::foo3

    hi, i am in tt2::foo3

    hi, i am in tt2::foo3

      请注意第二行输出,tt2_foo3取的是&tt2::foo3,但由于传递的this指针产生是&x,所以实际上调用了tt1::foo3。同样,第三行输出,取的是基类的函数地址,但由于实际对象是派生类,最后调用了派生类的函数。这说明取得的成员函数地址在虚拟函数的情况下仍然保持了正确的行为。
      你若真的理解了上面所说的,一定会觉得奇怪。取函数地址的时候就得到了一个整数(成员函数地址),为何调用的时候却进了不同的函数? 只要看看汇编代码就都清楚了,"源码之前,了无秘密"。源代码: GetMemberFuncAddr_VC6(tt1_foo3,&tt1::foo3); 产生的汇编代码如下:

    push offset @ILT+90(`vcall') (0040105f)

    ...

      原来取tt1::foo3地址的时候,并不是真的就将tt1::foo3的地址传给了函数,而是传了一个vcall函数的地址。顾名思义,vcall当然是虚拟调用的意思。我们找到地址0040105f,看看这个函数到底干了些什么。

    @ILT+90(??_9@$BA@AE):

    0040105F jmp `vcall' (00401380)

    该地址只是ILT的一个项,直接跳转到真正的vcall函数,00401380。找到00401380,就可以看到vcall的代码。

    `vcall':

    00401380 mov eax,dword ptr [ecx] ;//将this指针视为dword类型,并将指向的内容(对象的首个dword)放入eax.

    00401382 jmp dword ptr [eax] ;//跳转到eax所指向的地址.

      代码执行的时候,ecx就是this指针,具体说就是上面对象x或y的地址。而eax就是对象x或y的第一个dword的值。我们知道,对于有虚拟函数的类对象,其对象的首地址处总是一个指针,该指针指向一个虚函数的地址表。上面的对象由于只有一个虚函数,所以虚函数表也只有一项。因此,直接跳转到eax指向的地址就好。如果有多个虚函数,则eax还要加上一个偏移量,以定位到不同的虚函数。比如,如果有两个虚函数,则会有两个vcall代码,分别对应不同的虚函数,其代码大概是下面的样子:

    `vcall':

    00401BE0 mov eax,dword ptr [ecx]

    00401BE2 jmp dword ptr [eax]

     

    `vcall':

    00401190 mov eax,dword ptr [ecx]

    00401192 jmp dword ptr [eax+4]

    编译器根据取的是哪个虚函数的地址,则相应的用对应的vcall地址代替。

      总结一下:用前面方法取得的成员函数地址在虚拟函数的情况下仍然保持正确的行为,是因为编译器实际上传递了对应的vcall地址。而vcall代码会根据上下文this指针定位到对应的虚函数表,进而调用正确的虚函数。
      最后,我们看一下多继承情况。很明显,现在情况要复杂得多。如果实际试一下,会碰到很多困难。首先,指定成员函数的时候可能会碰到冲突。其次,给定this指针的时候需要经过调整。另外,对虚拟继承可能还要特别处理。解决所有这些问题已经超出了这篇文章的范围,并且我想要的成员函数指针是一个真正的指针,而在多继承的情况下,很多时候成员函数指针已经变成了一个结构体(见参考文献),这时要正确调用该指针就变得格外困难。因此结论是,上面讨论的方法并不适用于多继承的情况,要想在多继承的情况下直接调用成员函数地址,必须手工处理各种调整,没有简单的统一方法。

    参考文献 成员函数指针与高性能的C++委托

     

    展开全文
  • C++ tips: 类成员函数参数默认值

    千次阅读 2015-06-07 19:32:58
    对于一个类的成员函数参数默认值,还是有一定讲究的。转载一篇文章,地址如下: http://en.cppreference.com/w/cpp/language/default_arguments 关键注意几点 (1)类的成员函数的默认值在声明和实现...

    对于一个类的成员函数的参数默认值,还是有一定讲究的。转载一篇文章,地址如下:


    http://en.cppreference.com/w/cpp/language/default_arguments


    关键注意几点

    (1)类的成员函数的默认值在声明和实现两个不同的地方,只能有一个地方对同一个参数设置默认值;

    (2)类的成员函数的默认值,可以是类的静态成员变量;

    (3)类的构造函数特殊注意;

    (4)基类的函数定义了默认值,但是继承类重载是没有定义默认值,那么继承类的对象的函数将不具备默认值;

    (5)不能用this指针作为成员函数的默认参数值


    对于不是类的成员函数,参数的默认值在上方的引用文章中也有描述。

    展开全文
  • c++ 成员函数作为函数指针参数传入

    千次阅读 2016-02-06 17:12:41
    c++ 成员函数作为函数指针参数传入 标签: c++treestruct图形c 2012-08-19 18:56 4239人阅读 评论(0) 收藏 举报 分类: C++(11) 数据结构(13) 版权声明:本文为博主原创...
  • 一个双目运算符作为类的成员函数重载时,重载函数的参数表中有()个参数。...若为成员函数重载,参数一般为类对象的引用,另一个参数this 指针所指向,故不显示。 若为友元函数重载,则有两个参数! ...
  • 非静态成员函数this指针

    千次阅读 2016-11-15 15:45:17
    this指针的本质This指针本质是一个函数参数...实际上,非静态成员函数默认的第一个参数为T* const this 例如,调用date.SetMonth(9) <===> SetMonth(&date, 9),this帮助完成了这一转换 . 所以,this指针并非类的成员
  • C++中,静态成员函数不能被声明为virtual函数。  例如,下面的程序会编译失败。 #include&lt;iostream&gt; class Test { public: // 编译错误:static成员函数不能声明为virtual virtual static ...
  • C++非静态成员函数this指针

    千次阅读 2018-03-17 14:02:18
    C++的类里,除了静态成员函数外(若想了解静态成员函数,可以点击这里static修饰的函数),每个成员函数都有一个额外的、隐含的形参this。当调用这个成员函数时,编译器它会向形参this传递调用成员函数的对象的地址...
  • this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它...
  • 测试这个功能的初衷是测试boost里面的bind ...其实成员函数和全局函数无非就是差一个this指针参数。给传进去不久也可以调用了。然而并没有那么简单。看了boost的源码表示太长了。没怎么看懂 然后就
  • C++ this指针与const成员函数

    千次阅读 2017-10-29 15:09:54
    C++ this指针与const成员函数this指针 每个对象拥有一个this指针,通过this指针来访问自己的地址。 this指针并不是对象的一部分,this指针所占的内存大小是不会反应在sizeof操作符上的。 this指针只能在成员函数中...
  • this指针是隐式的,并且它是成员函数的第一个参数。要注意的是构造函数比较特殊,它没有this指针;2. 编译器会对成员函数进行处理,在对象调用成员函数时,编译器将对象的地址作为实参传给传给成员函数的第一个形参...
  • 实际上所有线程都是用来处理C函数的,而不是C++类成员函数。标准库中提供一个API函数,这个函数以回调函数指针作为线程的执行代码并在单独的线程中调用回调函数。问题是在这样的线程库中不能创建执行对象成员函数的...
  • 成员函数作为pthread_create函数参数

    千次阅读 2016-01-14 11:30:24
    近日需要将线程池封装成C++类,类名为Threadpool。在类的成员函数exec_task中调用pthread_create去启动线程执行例程thread_rounter。编译之后报错如下: spfs_threadpool.cpp: In member functi
  • 成员变量作为成员函数的默认参数

    千次阅读 2016-06-03 17:02:38
    如何在类成员函数中默认引用类成员?class CAbc;class CAbc{private:int m_abc; public:void fun0(int &p=NULL)//编译错误{ printf("%d",p);}void fun1(const int &p=NULL)//编译通过{ printf("%d",p);}void fun2...
  • 指向成员函数的指针和this指针

    千次阅读 2019-05-07 20:32:49
    1.指向类的成员函数的指针 (1)定义的一般形式:数据类型 (类名:: * 指针变量名)(参数表列) (2)使成员函数指针指向类的共用成员函数的一般形式:函数指针名=&类名::函数名 (3)利用函数指针调用...
  • C++ Time类,有个private成员变量hours,然后类声明以后是不能直接 访问的 ,比如不能像这样 Time planning; planning.hours。不能这样使用是很明白的。但是却发现,在Time类的方法里面可以这样用, 很奇怪,这个...
  • 成员函数this指针的意义

    千次阅读 2016-07-08 00:17:32
    成员函数的调用:也是仍然点号或箭头,也受public/private的限制 使用隐含的this指针,来访问本对象的成员,this指针指向了对象自己 注:this指针是在形式上做了一个简化,使得用户少传一个对象的指针作为参数 ...
  • 一、函数指针(不是类的成员函数): 1、指针变量也可以指向一个函数。C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址,这个函数入口地址就称为函数的指针。 2、函数指针的作用: (1)...
  • C++:默认成员函数this指针

    千次阅读 2018-07-31 17:57:27
    this指针
  • ·静态成员函数 ·静态成员函数就是使用 static 关键字声明的成员函数  在类外实现时不加static关键字,只有在类内声明时才加static ·静态成员函数是类的一部分,作用是为了处理静态数据成员  没有this指针 ·...
  • const更大的魅力是它可以修饰函数参数、返回值,甚至函数的定义体。 (1)const修饰函数参数  1.如果输入的参数采用“指针传递”,那么加上const可以防止意外的改动该指针,起到保护作用  例
  • this与const成员函数不得不提二三事

    千次阅读 2014-06-07 23:02:33
    在编写C++代码时,由于个人习惯的不同,成员函数定义时(若有成员的调用),有些人喜欢指明this指针,而有些人又不乐意写this。当然,提这个并不是要说个人习惯的好坏,不知你是否想过:使用this时,你并未对其进行...
  • 其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递this指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数却-有...
  • C++中常量成员函数

    千次阅读 2018-08-14 16:22:35
    将const关键字放在类成员函数参数列表之后,表示该函数为常量成员函数。 class MyClass { public: int consFunc() const; private: int m_MyNum; }; 2 定义 可以在类内定义cons...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 332,375
精华内容 132,950
关键字:

成员函数的this参数