-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
joergboe
committed
Feb 9, 2021
1 parent
64d64ab
commit 1aa96ca
Showing
3 changed files
with
133 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,152 @@ | ||
//============================================================================ | ||
// Name : PointerToMember.cpp | ||
// Author : joergboe | ||
// Version : | ||
// Copyright : Your copyright notice | ||
// Description : Hello World in C++, Ansi-style | ||
//============================================================================ | ||
|
||
#include <iostream> | ||
using namespace std; | ||
|
||
class Base { | ||
public: | ||
char a; | ||
char b; | ||
|
||
Base(char a_, char b_) : a(a_), b(b_) {}; | ||
void print1(int val) { | ||
cout << "print1 a=" << a << " b=" << b << " val=" << val << endl; | ||
char const * mess; | ||
char a, b; | ||
char const cc; | ||
private: | ||
char privc; | ||
public: | ||
Base(char const * mess_ = "Base", char a_ = 'a', char b_ = 'b') : mess(mess_), a(a_), b(b_), cc('C'), privc('p') {}; | ||
void print1(int val) const { | ||
cout << "print1"; | ||
printVars(); | ||
cout << " val=" << val << endl; | ||
} | ||
/*void print2(int val) const { | ||
cout << "print2"; | ||
printVars(); | ||
cout << " val=" << val << endl; | ||
}*/ | ||
void setA(char c_) { | ||
a = c_; | ||
} | ||
void setB(char c_) { | ||
b = c_; | ||
} | ||
void print2(int val) { | ||
cout << "print2 a=" << a << " b=" << b << " val=" << val << endl; | ||
protected: | ||
void printVars() const { | ||
cout << " mess=" << mess << " a=" << a << " b=" << b << " privc=" << privc; | ||
} | ||
}; | ||
|
||
class Derived : public Base { | ||
public: | ||
char c; | ||
Derived(int a_, int b_) : Base(a_, b_), c('@') {}; | ||
char d; | ||
Derived() : Base("Derived", 'a'), d('d') {}; | ||
void print3(int val) { | ||
cout << "print3 a=" << a << " b=" << b << " c=" << c << " val=" << val << endl; | ||
cout << "print3"; | ||
printVars(); | ||
cout << " d=" << d << endl; | ||
} | ||
}; | ||
|
||
typedef char Base::* MemberPointer; | ||
typedef char Base::* MemberPointerB1; | ||
//using MemberPointer = char Base::*; //c11 stype | ||
typedef void (Base::*MethodPointer)(int); | ||
//using MethodPointer = void (Base::*)(int); | ||
|
||
int main() { | ||
cout << "!!!Hello World!!!" << endl; | ||
Base object1('a', 'b'); | ||
object1.print1(55); | ||
object1.print2(56); | ||
|
||
//Member Pointer | ||
char Base::* const memberPointer1 = &Base::a; //direct declaration (const) | ||
object1.*memberPointer1 = 'A'; | ||
MemberPointer memberPointer2 = &Base::b; | ||
object1.*memberPointer2 = 'B'; //declaration using alias (typedef / using | ||
//Method Pointer | ||
void (Base::*methodPointer1)(int) = &Base::print1; //direct declaration | ||
Base* objectPtr = &object1; | ||
(objectPtr->*methodPointer1)(11); | ||
MethodPointer methodPointer2 = &Base::print2; | ||
(object1.*methodPointer2)(22); | ||
|
||
//Derived | ||
Derived object2('x','y'); | ||
void (Derived::* methodPointer3)(int) = &Derived::print3; | ||
(object2.*methodPointer3)(22); | ||
methodPointer3 = &Derived::print1; | ||
(object2.*methodPointer3)(100); | ||
(object2.*methodPointer1)(0); //use method pointer of Base with object type Derived | ||
|
||
cout << "sizeof(object1)=" << sizeof(object1) << endl; | ||
cout << "sizeof(object2)=" << sizeof(object2) << endl; | ||
cout << "Demonstration of pointer to member and pointer to method.\n" | ||
"The declaration 'T C::* P' declares P as a pointer to non-static member of C of type T.\n" | ||
"Where member can be a non-static attribute or a non-static class function.\n" | ||
"Use operator '.*' (pointer to member of object) or '->*' (pointer to member of pointer)\n" | ||
"to access these members.\n" | ||
"Address operator '&C::member delivers the address for these pointers.\n" | ||
"Pointers to member must not be assigned to other pointer types an void*.\n" | ||
"The 'nullptr' can be assigned to a pointer to member.\n\n"; | ||
|
||
Base base1; | ||
base1.print1(1); | ||
|
||
cout << "\n****** Pointer to class member (non-static member) ******\n"; | ||
cout << "use 'char Base::* const char_ptr1' to declare a pointer to member\n"; | ||
cout << "use '&Base::a' to define the pointer\n"; | ||
char Base::* char_ptr1 = &Base::a; | ||
cout << "use 'base1.*char_ptr1' to address where it points to.\n"; | ||
cout << base1.*char_ptr1 << endl; | ||
cout << "char_ptr1 may point to all non-const char members of Base\n"; | ||
char_ptr1 = &Base::b; | ||
cout << base1.*char_ptr1 << endl; | ||
cout << "The member must be visible in that context:\n"; | ||
//char_ptr1 = &Base::privc; //error: ‘char Base::privc’ is private within this context | ||
cout << "the pointer can be const qualified with 'char Base::* const char_ptr2 = &Base::a'\n"; | ||
char Base::* const char_ptr2 = &Base::a; | ||
cout << "base1.*char_ptr2: " << base1.*char_ptr2 << endl; | ||
cout << "constantness is maintained\n"; | ||
//char_ptr2 = &Base::b; //error: assignment of read-only variable ‘char_ptr2’ | ||
//char_ptr1 = &Base::cc; //error: invalid conversion from ‘const char Base::*’ to ‘char Base::*’ [-fpermissive] | ||
Base const base2("Base const"); | ||
//base2.*char_ptr1 = 'x'; //error: assignment of read-only location ‘*(((const char*)(& base2)) + ((sizetype)char_ptr1))’ | ||
const char * Base::* mess_ptr = &Base::mess; | ||
cout << "base2.*mess_ptr: " << base2.*mess_ptr << endl; | ||
|
||
cout << "\nPointer to members can be used with objects of public derived classes\n"; | ||
Derived derived1; | ||
cout << "derived1.*mess_ptr: " << derived1.*mess_ptr << endl; | ||
cout << "But pointers to members of derived can not point to members of base\n"; | ||
char Derived::* char_ptr3 = &Derived::d; | ||
cout << "derived1.*char_ptr3: " << derived1.*char_ptr3 << endl; | ||
//base1.*char_ptr3 = 'x'; //error: pointer to member type ‘char’ incompatible with object type ‘Base’ | ||
|
||
cout << "\nRecomended use of aliases:\n"; | ||
typedef char Base::* BaseToCharMemberPtr; | ||
using BaseToMessMemberPtr = char const * Base::*; //c11 stype | ||
BaseToCharMemberPtr mptr3 = &Base::b; | ||
BaseToMessMemberPtr mptr4 = &Base::mess; | ||
cout << "base2.*mptr4: " << base2.*mptr4 << " base2.*mptr3: " << base2.*mptr3 << endl; | ||
|
||
cout << "\nUse operator '->*' with an object pointer\n"; | ||
Base const * b_cptr = & base2; | ||
cout << "b_cptr->*mptr4: " << b_cptr->*mptr4 << " b_cptr->*mptr3: " << b_cptr->*mptr3 << endl; | ||
|
||
cout << "\n****** Pointer to class member functions (non-static member) ******\n"; | ||
|
||
cout << "Function pointer declaration rules and '::*' declares a pointer to a visible member function:\n" | ||
"void (Base::*func_ptr1)(char) = &Base::setA\n"; | ||
void (Base::*func_ptr1)(char) = &Base::setA; | ||
cout << "the usage of this pointer requires parentheses:\n"; | ||
(base1.*func_ptr1)('x'); | ||
cout << "a pointer of this type can point to any member function with a matching signature.\n"; | ||
func_ptr1 = &Base::setB; | ||
(base1.*func_ptr1)('y'); | ||
base1.print1(12); | ||
cout << "The member must be visible in that context:\n"; | ||
//void (Base::*func_ptr2)() = &Base::printVars; //error: ‘void Base::printVars()’ is protected within this context | ||
cout << "\nPointer to members can be used with objects of public derived classes\n"; | ||
(derived1.*func_ptr1)('z'); | ||
derived1.print1(0); | ||
cout << "const qualifier is part of the function pointer type:\n"; | ||
void (Base::*func_ptr_const)(int) const = &Base::print1; | ||
cout << "type func_ptr1: " << typeid(func_ptr1).name() << | ||
"\ntype func_ptr_const: " << typeid(func_ptr_const).name() << endl; | ||
cout << "Use with a pointer to object (b_cptr->*func_ptr_const)(14)\n"; | ||
(b_cptr->*func_ptr_const)(14); | ||
Derived * d_ptr = & derived1; | ||
(d_ptr->*func_ptr_const)(15); | ||
|
||
cout << "\nRecomended use of aliases:\n"; | ||
typedef void (Base::*BaseSetCharMemberFunctionPointer)(char); | ||
using BasePrintMemberFunctionPointer = void (Base::*)(int) const; | ||
BaseSetCharMemberFunctionPointer fmp1 = &Base::setA; | ||
BasePrintMemberFunctionPointer fmp2 = &Base::print1; | ||
(base1.*fmp1)('@'); | ||
(base1.*fmp2)(999); | ||
|
||
cout << "\n****** pointer to member and pointer ******\n" | ||
"Pointer to member can not be assigned to a 'void *'\n"; | ||
// void * vptr = func_ptr1; //error: cannot convert ‘void (Base::*)(char)’ to ‘void*’ in initialization | ||
cout << "Can assign 'nullptr' to pointer to member but never use such member! The result is undefined.\n"; | ||
char_ptr1 = nullptr; | ||
|
||
cout << "END" << endl; | ||
|
||
return 0; | ||
} |