cpp——类——成员指针

概述

this为const指针对象,指向当前实例对象,因此this的本质就是实例对象,non-static数据成员和non-static函数成员跟this相关联,而static数据成员和static函数成员跟this无关联,因此non-static数据成员和non-static函数成员属于实例对象成员,而static数据成员和static函数成员则不属于实例对象成员
同一类作用域内的所有成员(non-static数据成员,non-static函数成员,static数据成员,static函数成员)本质位于同一作用域,而对象名字定义search ignored对象名字的类型,因此同一类作用域内的所有成员名字不能重复(成员名字都是定义)
class CAnimal
{
public:
    int getTotalAnimal();
    
public:
    int totalAnimal;
    
public:
    static int getTotalAnimal();
    
public:
    static int totalAnimal;
};
注:编译error,getTotalAnimal和totalAnimal重复定义

成员指针

class CAnimal
{
public:
    CAnimal() : mGroup(1) {}
    
public:
    int mGroup;
    
public:
    void init() { cout << "CAnimal::init()" << endl; }
    
public:
    static int totalGroup;
    
public:
    static int getTotalGroup() { cout << "CAnimal::getTotalGroup()" << endl; return totalGroup; }
};

int CAnimal::totalGroup = 5;

class CDog : public CAnimal
{
public:
    CDog() : mGroup(2) {}
    
public:
    int mGroup;
    
public:
    void init() { cout << "CDog::init()" << endl; }
    
public:
    static int totalGroup;
    
public:
    static int getTotalGroup() { cout << "CDog::getTotalGroup()" << endl; return totalGroup; }
};

int CDog::totalGroup = 8;

void member_pointer()
{
    cout << "-----static-----" << endl;
    
    int* pAnimalStaticData = &CAnimal::totalGroup;
    int (*pAnimalStaticFun)() = CAnimal::getTotalGroup;
    
    cout << "totalGroup = " << *pAnimalStaticData << endl;
    pAnimalStaticFun();
    
    pAnimalStaticData = &CDog::totalGroup;
    pAnimalStaticFun = CDog::getTotalGroup;
    
    cout << "totalGroup = " << *pAnimalStaticData << endl;
    pAnimalStaticFun();
    
    cout << "-----non static-----" << endl;
    
    int CAnimal::*pAnimalNonStaticData1 = &CAnimal::mGroup;
    //int CAnimal::*pAnimalNonStaticData2 = &CDog::mGroup;
    
    void (CAnimal::*pAnimalNonStaticFun1)() = &CAnimal::init;
    //void (CAnimal::*pAnimalNonStaticFun2)() = &CDog::init;
    
    int CDog::*pDogNonStaticData1 = &CAnimal::mGroup;
    int CDog::*pDogNonstaticData2 = &CDog::mGroup;
    
    void (CDog::*pDogNonStaticFun1)() = &CAnimal::init;
    void (CDog::*pDogNonStaticFun2)() = &CDog::init;
    
    CDog dog;
    CDog* pDog = &dog;
    CAnimal animal = dog;
    CAnimal* pAnimal = &animal;
    
    cout << "mGroup = " << animal.*pAnimalNonStaticData1 << endl;
    cout << "mGroup = " << dog.*pAnimalNonStaticData1 << endl;
    //cout << "mGroup = " << animal.*pDogNonStaticData1 << endl;
    cout << "mGroup = " << dog.*pDogNonStaticData1 << endl;
    //cout << "mGroup = " << animal.*pDogNonstaticData2 << endl;
    cout << "mGroup = " << dog.*pDogNonstaticData2 << endl;
    
    (animal.*pAnimalNonStaticFun1)();
    (dog.*pAnimalNonStaticFun1)();
    //(animal.*pDogNonStaticFun1)();
    (dog.*pDogNonStaticFun1)();
    //(animal.*pDogNonStaticFun2)();
    (dog.*pDogNonStaticFun2)();
    
    cout << "mGroup = " << pAnimal->*pAnimalNonStaticData1 << endl;
    cout << "mGroup = " << pDog->*pAnimalNonStaticData1 << endl;
    (pAnimal->*pAnimalNonStaticFun1)();
    (pDog->*pAnimalNonStaticFun1)();
}
output:
-----static-----
totalGroup = 5
CAnimal::getTotalGroup()
totalGroup = 8
CDog::getTotalGroup()
-----non static-----
mGroup = 1
mGroup = 1
mGroup = 1
mGroup = 2
CAnimal::init()
CAnimal::init()
CAnimal::init()
CDog::init()
mGroup = 1
mGroup = 1
CAnimal::init()
CAnimal::init()

总结

  • 从实例对象角度看,父类成员既属父类,也属子类,反之,子类成员只属子类,不属父类,从类作用域角度看,子类作用域嵌套于父类作用域,因此子类既可访问子类作用域,也可访问父类作用域,反之,父类只可访问父类作用域,不可访问子类作用域
  • 对于static数据成员和static函数成员,类只有类作用域的含义,跟this无关联,因此引用static数据成员和static函数成员的指针定义跟普通非成员指针定义无区别
  • 对于non-static数据成员和non-static函数成员,类既有类作用域的含义,也跟this相关联,因此引用non-static数据成员和non-static函数成员的指针定义跟普通非成员指针定义有区别,通过成员指针定义符(::*)定义non-static数据成员和non-static函数成员的指针,::*前标识类类型(表示指针引用成员与this相关联),::*后标识成员指针对象
  • 成员指针运算符.*或->*,前者通过实例对象操作,后者通过实例对象指针操作,注意成员指针运算符和函数调用运算符的优先级关系,函数调用运算符优先级高于成员指针运算符优先级,通过成员指针运算符.*或->*访问成员指针时,把运算符前实例对象地址传给this隐含参数,因此子类可访问父类成员指针,父类不可访问子类成员指针,因为子类指针可隐式转换为父类指针,反之,父类指针不可隐式转换为子类指针
  • 子类实例对象包含父类成员,因此子类成员指针既可引用子类成员,也可引用父类成员,反之,父类实例对象不包含子类成员,因此父类成员指针只可引用父类成员,不可引用子类成员,因此可通过子类实例对象访问父类成员指针(因为子类包含最终访问的成员),反之,不可通过父类实例对象访问子类成员指针(因为父类不一定包含最终访问的成员)
  • 取static数据成员地址时,必须使用取地址操作符(&),如果不使用取地址操作符(&),获取的是static数据成员值,取non-static数据成员地址时,也必须使用取地址操作符(&),如果不使用取地址操作符(&),在类内部表示取特定类作用域内数据成员值
  • 取static函数成员地址时,跟取普通非成员函数地址相同,取地址操作符(&)optional,可omit,取non-static函数成员地址时,必须使用取地址操作符(&),不可omit,此时取地址操作符(&)表示this隐含参数
  • 取类成员(static数据成员,static函数成员,non-static数据成员,non-static函数成员)地址时,必须遵守对应类成员访问权限规则,否则就可通过类成员指针间接访问本不应该允许访问的成员

你可能感兴趣的:(cpp)