精华内容
下载资源
问答
  • C++ 类成员函数的函数指针 万次阅读 多人点赞
    2018-08-23 18:40:17

    一、引言

    当我们在 C++ 中直接像 C 那样使用类的成员函数指针时,通常会报错,提示你不能使用非静态的函数指针:

    reference to non-static member function must be called

    两个解决方法:

    1. 把非静态的成员方法改成静态的成员方法
    2. 正确的使用类成员函数指针(在下面介绍)

     

    关于函数指针的定义和使用你还不清楚的话,可以先看这篇博客了解一下:

    https://blog.csdn.net/afei__/article/details/80549202

     

    二、语法

    1. 非静态的成员方法函数指针语法(同C语言差不多):

    void (*ptrStaticFun)() = &ClassName::staticFun;

    2. 成员方法函数指针语法:

    void (ClassName::*ptrNonStaticFun)() = &ClassName::nonStaticFun;

    注意调用类中非静态成员函数的时候,使用的是 类名::函数名,而不是 实例名::函数名

     

    三、实例:

    #include <stdio.h>
    #include <iostream>
      
    using namespace std;
      
    class MyClass {
    public:
        static int FunA(int a, int b) {
            cout << "call FunA" << endl;
            return a + b;
        }
      
        void FunB() {
            cout << "call FunB" << endl;
        }
      
        void FunC() {
            cout << "call FunC" << endl;
        }
      
        int pFun1(int (*p)(int, int), int a, int b) {
            return (*p)(a, b);
        }
      
        void pFun2(void (MyClass::*nonstatic)()) {
            (this->*nonstatic)();
        }
    };
      
    int main() {
        MyClass* obj = new MyClass;
        // 静态函数指针的使用
        int (*pFunA)(int, int) = &MyClass::FunA;
        cout << pFunA(1, 2) << endl;
         
        // 成员函数指针的使用
        void (MyClass::*pFunB)() = &MyClass::FunB;
        (obj->*pFunB)();
         
        // 通过 pFun1 只能调用静态方法
        obj->pFun1(&MyClass::FunA, 1, 2);
         
        // 通过 pFun2 就是调用成员方法
        obj->pFun2(&MyClass::FunB);
        obj->pFun2(&MyClass::FunC);
     
        delete obj;
        return 0;
    }

    更多相关内容
  • 成员函数(简称函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也返回值和函数类型,它与一般函数的区别只是:它是属于一个的成员,出现在体中。它可以被指定为private(私有的...

    类的成员函数(简称类函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也有返回值和函数类型,它与一般函数的区别只是:它是属于一个类的成员,出现在类体中。它可以被指定为private(私有的)、public (公用的)或protected(受保护的)。

    在使用类函数时,要注意调用它的权限(它能否被调用)以及它的作用域(函数能使用什么范围中的数据和函数)。例如私有的成员函数只能被本类中的其它成员函数所调用,而不能被类外调用。成员函数可以访问本类中任何成员(包括私有的和公用的),可以引用在本作用域中有效的数据。

    一般的做法是将需要被外界调用的成员函数指定为public,它们是类的对外接口。但应注意,并非要求把所有成员函数都指定为public。有的函数并不是准备为外界调用的,而是为本类中的成员函数所调用的,就应该将它们指定为private。这种函数的作用是支持其它函数的操作,是类中其它成员的工具函数(utility function),类外用户不能调用这些私有的工具函数。

    类的成员函数是类体中十分重要的部分。如果一个类中不包含成员函数,就等同于C语言中的结构体了,体现不出类在面向对象程序设计中的作用。

    在类外定义成员函数

    在前面已经看到成员函数是在类体中定义的。也可以在类体中只写成员函数的声明,而在类的外面进行函数定义。如:

    class Student
    {
    public :
    void display( ); //公用成员函数原型声明
    private :
    int num;
    string name;
    char sex;
    //以上3行是私有数据成员
    };
    void Student::display( )//在类外定义display类函数
    {
    cout<<"num:"<<num<<endl;
    cout<<"name:"<<name<<endl;
    cout<<"sex:"<<sex<<endl;
    }
    Student stud1,stud2; //定义两个类对象
    

    注意:在类体中直接定义函数时,不需要在函数名前面加上类名,因为函数属于哪一个类是不言而喻的。

    但成员函数在类外定义时,必须在函数名前面加上类名,予以限定(qualifed)," :: "是作用域限定符(field qualifier)或称作用域运算符,用它声明函数是属于哪个类的。

    如果在作用域运算符“::”的前面没有类名,或者函数名前面既无类名又无作用域运算符“::”,如
    ::display( ) 或 display( )
    则表示display函数不属于任何类,这个函数不是成员函数,而是全局函数,即非成员函数的一般普通函数。

    类函数必须先在类体中作原型声明,然后在类外定义,也就是说类体的位置应在函数定义之前,否则编译时会出错。

    虽然函数在类的外部定义,但在调用成员函数时会根据在类中声明的函数原型找到函数的定义(函数代码),从而执行该函数。

    在类的内部对成员函数作声明,而在类体外定义成员函数,这是程序设计的一种良好习惯。如果一个函数,其函数体只有2-3行,一般可在声明类时在类体中定义。多于3行的函数,一般在类体内声明,在类外定义。

    展开全文
  • C++成员函数

    千次阅读 2021-06-08 10:00:48
    1.1 C++类成员函数的性质 类的成员函数是函数的一种,它的用法和作用和一般函数基本上是一样的,它也返回值和函数类型。它与一般函数的区别只是:它是属于一个类的成员,出现在类体中。它可以被指定为private...

    1 C++类的成员函数

    1.1 C++类成员函数的性质

           类的成员函数是函数的一种,它的用法和作用和一般函数基本上是一样的,它也有返回值和函数类型。它与一般函数的区别只是:它是属于一个类的成员,出现在类体中。它可以被指定为private(私有的),public(公用的)或protected(受保护的)。

           在使用类成员函数的时候,要注意调用它的权限(即,它能否被调用)以及它的作用域(函数能使用什么范围中的数据和函数)。例如,私有的成员函数只能被本类中的其他成员函数所调用,而不能被类外调用。成员函数可以访问本类中任何成员(包括私有的和公用的),可以引用在本作用域中有效的数据。

           所以,定义类的成员函数时,可以将需要被外界调用的成员函数指定为public,它们是类的对外接口。但应注意,并非要求把所有成员函数都指定为public。有的函数并不是准备为外界调用的,而是为本类中的成员函数所调用的,就应该将它们指定为private。

           类的成员函数是类体中十分重要的部分,如果一个类中不包含成员函数,就等同于C语言中的结构体类,体现不出类在面向对象程序设计中的作用。

    1.2 在类外定义成员函数

           前面看到的成员函数是在类体中定义的,那么,也可以在类体中只写成员函数的声明,而在类外面进行函数定义,例如:

    class student       //class开头

    {

    private:    //以下的部分是私有部分

        char name[32];

        char addr[32];

        long long number;//以上3 行是成员变量

    public:     //以下部分是公有部分

        student(char* pn, char* pa, long long n)

        {

            strcpy(name, pn);

            strcpy(addr, pa);

            number = n;

        }

        void print();       //这是成员函数

    };

    void student::print()       //这是成员函数

    {

        cout << "name = " << name << endl;

        cout << "addr = " << addr << endl;

        cout << "number = " << number << endl;

    }

           注意:在类体中直接定义函数时,不需要在函数名前面加上类名,因为函数就属于当前定义该函数的类。但成员函数在类外定义的时候,必须在函数名前面加上类名,“::”是作用域限定符或称作用域运算符,用它声明函数是属于哪个类的。

    例如,student::print() 表示作用域为student类的print()函数,也就是student类中的print()函数。如果没有“student::”的限定,print()指的是它所在的作用域中的print()函数,就是一个普通的函数,不属于student类。对上面程序段而言,就是指全局作用域中的print()函数,而不是student类中的print()函数。而且不同的类中可能有同名的函数,用作用域限定符加以限定,就明确地说明了是哪一个作用域的函数,也就是哪一个类的函数。

           如果在作用域运算符“::”的前面没有类名,或者函数名前面既无类名,又无作用域运算符“::”,如:

    ::print()          或          print()

    就表示 print() 函数不属于任何类,这个函数不是成员函数,而是全局函数,即非成员函数的一般普通函数。

           类函数必须先在类体中作原型声明,然后,在类外定义,也就是说类体的位置应在函数定义之前(如上面所示的那样),否则编译时会出错。

           虽然函数在类外部定义,但在调用成员函数时会根据在类中声明的函数原型找到函数的定义(函数代码),从而执行该函数。

    韦凯峰 Linux C/C++ 程序设计教程,Linux 系统编程,Openwrt 系统开发,微信:13926572996,QQ:1523520001,博客:www.mylinux.vip

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

    千次阅读 2019-05-14 21:23:08
    这些默认的类成员函数, 在类创建的时候, 编译器会自动调用, 但是自动调用并不意味着他们能完成用户所期待的所有任务, 像构造函数, 析构函数, 拷贝构造函数, 赋值重载会在某些情况下需要用户根据程序的需要自定义实现...

    6个默认成员函数

    在这里插入图片描述
    这些默认的类成员函数, 在类创建的时候, 编译器会自动调用, 但是自动调用并不意味着他们能完成用户所期待的所有任务, 像构造函数, 析构函数, 拷贝构造函数, 赋值重载会在某些情况下需要用户根据程序的需要自定义实现.

    构造函数

    构造函数的主要工作是在对象创建的时候就完成初始化工作.
    特性

    1. 函数名与类名相同。
    2. 无返回值。
    3. 对象实例化时编译器自动调用对应的构造函数。
    4. 构造函数可以重载。
      自定义构造函数:
      用户自定义构造函数完成了对私有成员_year, _month, _day的初始化工作.在一般类定义中, 可以通过缺省参数来代替构造函数的重载, 因为这种方式更加灵活和安全.
      在这里插入图片描述
      编译器调用默认构造函数:
      如果用户没有自定义构造函数, 则编译器会自动调用一个默认的不带参数的构造函数, 但是编译器调用的默认构造函数不会对普通成员变量造成影响, 但是会让自定义类型变量去调用该类的默认构造函数.
      在这里插入图片描述
      运行效果:
      在这里插入图片描述
      注意: 所谓的默认构造函数是指可以不用传参的构造函数.

    析构函数:

    当对象在销毁时会自动调用析构函数完成类的一些资源清理工作.
    特性:

    1. 析构函数名是在类名前加上字符 ~。
    2. 无参数无返回值。
    3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
    4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
      自定义析构函数:
      一般在堆中开辟的内存在对象销毁后不会自动释放资源, 需要程序员手动释放, 此时就会用到析构函数的自定义.
      在这里插入图片描述
      编译器调用默认析构函数:
      如果用户不自定义析构函数, 则编译器会自动调用默认的析构函数, 同自动调用的构造函数一样, 自动调用的析构函数依然不会对普通成员变量造成影响, 但是会让自定义类型变量调用该类的默认析构函数.
      在这里插入图片描述
      效果图:
      在这里插入图片描述

    拷贝构造函数:

    当创建对象时把对象作为参数传进去完成对象的拷贝初始化.
    特性:

    1. 拷贝构造函数是构造函数的一个重载形式。
    2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
      自定义拷贝构造函数:
      在这里插入图片描述
      效果图:
      在这里插入图片描述
      也可以通过 Date d_tmp = d; 这也是调用拷贝构造函数.
      编译器调用默认拷贝构造函数:
      与编译器调用默认的构造函数和析构函数不同的是, 拷贝构造函数完成了一定的工作, 就是类似与上述自定义实现的内容, 将存在的对象的属性拷贝给新创建的对象, 完成初始化工作.

    运算符重载(赋值重载)

    运算符重载中的赋值重载是默认的成员函数, 对于两个已存在的对象, 将一个对象赋值给另一个对象, 完成赋值操作.

    C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
    函数名字为:关键字operator后面接需要重载的运算符符号。
    函数原型:返回值类型 operator操作符(参数列表)

    运算符重载特性:
    1.不能通过连接其他符号来创建新的操作符:比如operator@
    2.重载操作符必须有一个类类型或者枚举类型的操作数
    3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
    4.作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的
    操作符有一个默认的形参this,限定为第一个形参
    5. .* 、:: 、sizeof 、?:. 注意以上5个运算符不能重载。
    自定义赋值重载:
    在这里插入图片描述
    效果图:
    在这里插入图片描述
    编译器调用默认赋值重载
    同编译器调用的默认拷贝构造函数一样, 赋值重载会完成上述自定义赋值重载类似的工作, 将一个对象的属性赋值给另一个已存在对象, 使这两个对象具有相同的属性.
    连续赋值:
    在这里插入图片描述
    如果不考虑效率问题, 传值调用的话, 连续赋值d1 = d2 = d3就会出现问题, 但是, 在本质上并不是因为没有传引用, 而是因为上述自定义拷贝构造函数的问题, 编译器默认调用的拷贝构造函数的参数类型其实为 const Date&, 在连续赋值的过程中会有临时变量调用拷贝构造, 临时变量具有常性, 不能将const Date& 转换成 Date&, 因此const参数传入的话会产生错误.
    在这里插入图片描述
    这其实是在警示我们, 在写成员函数的时候, 对于参数类型, 如果不改变内置类型的值或自定义类型的成员变量, 就加上 const, 自定义类型就加&; 对于返回值来说, 如果返回对象出函数外依然存在, 就加上&.

    const成员

    在这里插入图片描述
    这个成员函数为 const 成员函数, 本质上其实是:
    在这里插入图片描述
    因为this是隐式的, 所以不能由程序员自己去定义, 因此, 通过在函数名后加 const 其实就是修饰了this指针.
    这意味这, 成员变量就无法修改了.

    取地址及const取地址操作符重载

    在这里插入图片描述
    这两个取地址重载一般由编译器默认生成, 除非特殊情况, 一般不需要重新重载.

    展开全文
  • 首先我们定义一个Ctest,里面包含三个不同形式的成员函数,静态成员函数statFunc()、动态成员函数dynFunc()和虚拟函数virtFunc()。在main函数中我们利用cout标准输出流分别输出这三个函数的地址,程序如下所示:...
  • 的静态成员与静态成员函数

    千次阅读 2020-08-14 22:49:54
    声明静态成员 使用的静态成员 定义静态成员 静态成员内初始化 静态成员能用于某些场景,而普通函数不能
  • c++的几种成员函数声明后必须要定义吗? 1. 构造函数和析构函数 test.h #pragma once class CTest { public: CTest(); ~CTest(); }; test.cpp #include "stdafx.h" #include "test.h" 情况一: main.cpp #...
  • 模板(及其成员函数)的定义中,我们将模板参数当作替身,代替使用模板时用户提供的类型或值。 代码示例: template <typename T> //用T这个模板类型参数,来表示A中保存的元素的类型。 //当用户实例化A...
  • 成员函数(简称函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也返回值和函数类型,它与一般函数的区别只是:它是属于一个的成员,出现在体中。它可以被指定为private(私有的...
  • 外定义成员函数 成员函数可以在体中直接定义。也可以在体中只写成员函数的声明,而在的外面进行函数定义。如: class Student { public : void display( ); //公用成员函数原型声明 private : int ...
  • 一般来说,非成员函数应是友元函数,这样它才能直接访问的私有数据。 例如,Time的加法运算符在Time声明中的原型如下: Timeoperator+(constTime &amp; t) const; //成员函数版本 这个也可以使用...
  • 1,一个普通的一个成员函数可以成为模板成员函数么? 答案是可以的,实例如下 #include&lt;iostream&gt; #include&lt;string&gt; using namespace std; class PrintIt { public: PrintIt...
  • 浅谈C++中6个成员函数

    千次阅读 多人点赞 2021-03-18 15:45:13
    构造函数是一个特殊的成员函数,名字与类名相同且不能返回值,创建类型时由编译器自动调用,在对象的生命周期内只调用一次。**主要任务是初始化对象。 ↓下面是一个简单的构造函数(全缺省): 主函数初始化时...
  • 在继承之外,在C++中一个类成员函数调用另一个类成员的方法主要:类的组合,友元类,类的前向声明,单例模式等,下面主要讲讲这4种方法的实现 方法1:利用类的组合 组合通俗来讲就是类B类A的属性,如声明一个...
  • C++中和对象以及成员函数

    千次阅读 2017-11-17 16:57:23
    一个实体拥有自己的属性和行为,属性是私有的,行为是共有的,在C++中实体对应的就是对象,实体抽象数据类型就是,属性是成员变量,行为是成员函数。 面向对象思想的三大特征: 封装、继承、多态(静多态,动多态...
  • 类成员函数和全局函数

    千次阅读 2015-10-28 20:45:38
    类成员函数和全局函数的对比:  1.类成员函数和全局函数的区别就是,一个是面向对象,一个是面向过程  2.类成员函数==(转成)==>全局函数:增加一个参数,增加的这个参数是代替this指针的  3.全局函数==(转...
  • 成员函数:无论静态函数还是非静态函数,都是属于的(这一点与数据成员的静态非静态不同),对象并不拥有函数的拷贝.两者的区别在于:非静态的函数由对象(加.或指针加->;)调用,这时将向函数传递this指针.而静态函数由...
  • c++类成员函数作为回调函数

    万次阅读 多人点赞 2016-06-29 22:44:30
    最近又仔细学了会,感觉回调函数,我认为就是将一个函数指针A作为参数传入另外一个函数B,然后在函数B中调用函数A。  普通回调  具体先看一个简单的例子:   #include void printWelcome(int len) { printf(...
  • 当成员变量是私有的时候,要对它们初始化就必须用一个公有的成员函数来进行。同时这个成员函数应在仅且在对象定义时自动的执行一次,这个函数我们就叫做构造函数。2. 构造函数的特点(1)函数名与类名相同;(2)无...
  • 类成员函数作为线程函数使用

    万次阅读 多人点赞 2017-01-11 11:37:50
    类成员函数作为线程函数使用 C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象。函数体可以通过显示调用该指针或直接访问类内成员。 回调函数是用指针来调用的函数,最常使用的回调...
  • 的默认成员函数

    千次阅读 2018-07-31 01:37:26
    默认生成的成员函数有六个,它们分别是:构造函数、拷贝构造函数、析构函数、赋值操作符重载、取地址操作符重载和const修饰的取地址操作符重载。 一、构造函数 1、什么是构造函数? 初始化对象,且仅在定义一...
  • 什么是成员函数和非成员函数

    千次阅读 2015-03-23 13:10:38
    类有成员变量和成员函数。而函数中,不是任何一个的成员的函数,就是非成员函数。例如: class A{ public:  void f1(){}; // 这个就是成员函数。  void f2(); // 这个也是成员函数声明,其实现在的...
  • c++的成员变量和成员函数详解

    千次阅读 2019-04-09 14:38:18
    可以看做是一种数据类型,它类似于普通的数据类型,但是又别于普通的数据类型,这种类型是一个包含成员变量和成员函数的集合。 的成员变量和普通变量一样,也数据类型和名称,占用固定长度的内存。但是,...
  • 例如私有的成员函数只能被本中的其它成员函数所调用,而不能被外调用。成员函数可以访问本中任何成员(包括私有的和公用的),可以引用在本作用域中有效的数据。 一般的做法是将需要被外界调用的成员函数指定为...
  • 先写一个日期,把构造函数,拷贝构造函数,析构函数,赋值运算符的重载都写上,代码如下:class Date{ public: //构造函数 Date() { cout &lt;&lt; "Date()" &lt;&lt; endl; } //...
  • 虚函数---成员函数

    千次阅读 2019-03-27 17:48:12
    虚函数—成员函数 说明:在成员函数前面添加virtual关键字 ----那么这个函数就成员了虚函数 如果一个中存在虚函数,那么这个的对象中包含一个虚表(虚表首地址) 虚表在对象空间的开始位置 class Data { ...
  • C++的虚成员函数

    千次阅读 2017-04-19 21:12:12
    虚函数就是成员函数前面加上virtual关键字的函数。虚函数的作用就是为了实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。...
  • 不小心犯了一个错误, 导致项目代码编译不过,项目使用的语言是c++,一直报’bind(,xxxx)这类似的错误,开始以为是基础基类的方法问题,但查看代码之后发现,我们要bind的成员函数不是虚函数,也没有继承基类的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 531,861
精华内容 212,744
关键字:

哪个不是类必须有成员函数