C/C++疑问之存取结构体成员的点运算符(.)和箭头运算符(->)的区别



C/C++疑问之

存取结构体成员的点运算符(.)和箭头运算符(->)的区别

C:

相同点:两个都是二元操作符,其右操作符是成员的名称

不同点:点操作符左边的操作数是一个结果为结构的表达式箭头操作符左边的操作数是一个指向结构的指针

*主要看左边的操作符,左边是指针用箭头,否则用点。

快去写出程序实现吧,看看有什么区别。

*建议打印出地址,以便理解

typedefintDataType;

typedefstructQueue{

   intfront;

……

}LoopQueue;

 

voidTry(LoopQueue&q){

   q.front=q.rear=0;

   printf("front:%d\nrear:%d\n",q.front,q.rear);

}

……

C++:

语法

postfix-expression.name

postfix-expression>name
备注:

成员访问运算符.->用来引用结构、联合和类的成员。成员访问表达式具有选定成员的值和类型。

有两种形式的成员访问表达式:

在第一种形式中,postfix-expression表示结构、类或联合类型的值,name为指定的结构、联合或类的成员命名。运算的值是name的值且为左值(如果postfix-expression是左值)。

在第二种形式中,postfix-expression表示指向结构、联合或类的指针,name为指定的结构、联合或类的成员命名。该值是name的值且是左值。–>运算符取消引用该指针。因此,表达式e>member(*e).member(其中,e表示指针)会产生相同的结果(重载运算符–>*的情况除外)。

以下示例演示成员访问运算符的两种形式:

// expre_Selection_Operator.cpp

// compile with: /EHsc

#include <iostream>

using namespacestd;

 

struct Date{

    Date(inti,intj,intk): day(i), month(j),year(k){}

    intmonth;

    intday;

    intyear;

};

 

int main() {

    Date mydate(1, 1, 1900);

    mydate.month= 2;

    cout<< mydate.month << "/"<< mydate.day

         <<"/" << mydate.year << endl;

 

    Date *mydate2 = new Date(1, 1, 2000);

    mydate2->month= 2;

    cout<< mydate2->month << "/"<< mydate2->day

         <<"/" << mydate2->year << endl;

    deletemydate2;

}

这样的话出来的两个值分别为:

2/1/19992/1/2000

员运算符:.*->*

语法

expression.*expression

expression>*expression

备注

指向成员的指针运算符(.*和–>*)返回表达式左侧上指定的对象的特定类成员的值。右侧必须指定该类的成员。下面的示例演示如何使用这些运算符:

// expre_Expressions_with_Pointer_Member_Operators.cpp

// compile with: /EHsc

#include <iostream>

 

using namespacestd;

 

class Testpm{

public:

    voidm_func1() { cout << "m_func1\n";}

    intm_num;

};

 

// Define derived types pmfn and pmd.

// These types are pointers to members m_func1()and

// m_num, respectively.

void (Testpm::*pmfn)()= &Testpm::m_func1;

int Testpm::*pmd= &Testpm::m_num;

 

int main() {

    Testpm ATestpm;

    Testpm *pTestpm = new Testpm;

 

    //Access the member function

    (ATestpm.*pmfn)();

    (pTestpm->*pmfn)();  // Parentheses required since *binds

    //less tightly than the function call.

 

    //Access the member data

    ATestpm.*pmd= 1;

    pTestpm->*pmd= 2;

 

    cout<< ATestpm.*pmd << endl

         <<pTestpm->*pmd << endl;

    deletepTestpm;

}

Output();

m_func1();

m_func1();

 

结果分别为:

12

在前面的示例中,指向成员的指针pmfn用于调用成员函数m_func1。另一个指向成员的指针pmd用于访问m_num成员。
二元运算符.*将其第一操作数(必须是类类型的对象)与其第二操作数(必须是指向成员的指针类型)组合在一起。
二元运算符–>*将其第一操作数(必须是指向类类型的对象的指针)与其第二操作数(必须是指向成员的指针类型)组合在一起。
在包含.*运算符的表达式中,第一操作数必须是类类型且可访问,而指向第二操作数中指定的成员的指针或可访问类型的成员的指针明确从该类派生并且可供该类访问。
在包含–>*运算符的表达方式中,第一操作数必须是第二操作数中指定的类型的“指向类类型的指针”或明确地从该类派生的类型。
考虑以下类和程序段:

//expre_Expressions_with_Pointer_Member_Operators2.cpp

// C2440 expected

class BaseClass{

public:

    BaseClass();//Base class constructor.

    voidFunc1();

};

 

// Declare a pointer to member function Func1.

void (BaseClass::*pmfnFunc1)()= &BaseClass::Func1;

 

class Derived: public BaseClass{

public:

    Derived();//Derived class constructor.

    voidFunc2();

};

 

// Declare a pointer to member function Func2.

void (Derived::*pmfnFunc2)()= &Derived::Func2;

 

int main() {

    BaseClass ABase;

    Derived ADerived;

 

    (ABase.*pmfnFunc1)();  // OK: defined for BaseClass.

    (ABase.*pmfnFunc2)();  // Error: cannot use base classto

    //access pointers to members of

    //derived classes.

 

    (ADerived.*pmfnFunc1)();  // OK: Derived is unambiguously

    //derived from BaseClass.

    (ADerived.*pmfnFunc2)();  // OK: defined for Derived.

}

指向成员的指针运算符.*或–>*的结果是在指向成员的指针的声明中指定的类型的对象或函数。因此,在前面的示例中,表达式ADerived.*pmfnFunc1()的结果是指向返回void的函数的指针。如果第二操作数是左值,则此结果为左值。
System_CAPS_note
注意:如果某个指向成员的指针运算符的结果是函数,则该结果只能用作函数调用运算符的操作数。

 

猜你喜欢

转载自blog.csdn.net/ricardomtan/article/details/70834975