huangfu Blog
Love Leanote!
Toggle navigation
huangfu Blog
主页
About Me
归档
标签
07成员指针/运算符重载/友元函数/输入输出运算符重载
2017-02-11 22:42:01
40
0
0
tarena
#成员指针 ##成员变量指针 ###1. 概念 指向成员变量的指针 ###2. 语法 > 成员变量类型 类名::*指针名; class A { public: int x; int y; int z; }; /* 语法*/ int A::*pm; /* 如何赋值*/ pm = &A::x; /* 如何使用 专业术语:成员指针解引用*/ A a; a.*pm; A pa = new A; pa->*pm; ###3. 例子代码 #include <iostream> using namespace std; class Date { public: int year; int mon; int day; Date(int year, int mon, int day) :year(year), mon(mon), day(day) { } }; int main() { Date date(2017,02,10); /* 定义一个成员变量指针,指向mon成员*/ int Date:*pdate = &Date::mon; /* 成员变量指针解引用*/ cout << date.*pdate << endl; } ###4. 成员变量指针的本质 记录对象首地址的偏移量 验证代码: #include <iostream> using namespace std; class Date { public: int year; int mon; int day; Date(int year,int mon, int day) :year(year),mon(mon),day(day) { } }; int main() { union { int Date::*pdate; int *p; }; pdate = &Date::mon; cout << p << endl; // 4 } ##成员函数指针 ###1. 概念 指向普通成员函数的指针 ###2. 语法 class Date { int year; int mon; int day; public: int getYear() { return year; } int getMon() { return mon; } int getDay() { return day; } }; int (Date::*pfun)(); /* 这里注意要取地址,如果不取地址编译器会理解成静态成员函数*/ pfun = &Date::getMon; Date date; /* 这里要加个括号,表示优先级*/ (data.*fun)(); Date* pdate = new Date; (pdate->*fun)(); ###3. 举例(练习) #include <iostream> using namespace std; class Date { int year; int mon; int day; public: Date(int year = 2015,int mon = 1, int day = 1) :year(year),mon(mon),day(day) { } int getYear() { return year; } int getMon() { return mon; } }; int main() { Date date(2017,2,10); int (Date::*pdateFun)(); pdateFun = &Date::getMon; cout << (date.*pdateFun)() << endl; } ###4. 本质 成员函数的本质就是函数在代码区中的绝对地址 #运算符重载 ##1. 本质 一种函数的特殊表现形式 ##2. 举例 #include <iostream> using namespace std; class Fraction { public: int x; int y; Fraction(int x,inty) :x(x),y(y) { } void show() { cout << x << "/" << y << endl; } }; Fraction addoperactor(const Fraction& a, const Fraction& b) { /* 匿名对象简化编程*/ return Fraction(a.x*b.y + a.y*b.x, a.y*b.y); } Fraction operator+(const Fraction& a, const Fractionb) { return Fraction(a.x*b.y + a.y*b.x, a.y*b.y); } float operator*(const Fraction& a,const Fraction& b) { return static_cast<float>(a.x * b.x) / static_cast<float>(a.y * b.y); } void operator*=(Fraction& a,const Fraction& b) { a.x *= b.x; a.y *= b.y; } int main() { Fraction fa(1,2); Fraction fb(1,3); Fraction fc = addoperator(fa,fb); fc.show(); // 5/6 Fraction fd = fa + fb; fd.show(); // 5/6 cout << fa * fb << endl; // 1.6666 fa *= fb; fa.show(); // 1/6 } ##3. 总结 L#R 编译器会先去L对象对应的类型中找一个成员函数叫operator#(R) 如果没有就去全局函数中找一个全局函数叫operator#(L,R) 综合判断哪个最优调用哪个 成员操作符函数和全局操作符一般可以重载,单尽量不要重载 ##4. 成员操作符函数 #include <iostream> using namespace std; class Fraction { int x; int y; public: Fraction(int x = 1, int y = 1) :x(x),y(y) { } void show() { cout << x << '/' << y << endl; } Fraction operator+(const Fraction& b) { return Fraction(x*b.y + y*b.x, y*b.y); } Fraction operator*(const Fraction& b) { return Fraction(x*b.x, y*b.y); } void operator*=(const Fraction& b) { x *= b.x; y *= b.y; } }; int main() { Fraction fa(1,2); Fraction fb(1,3); Fraction fc = fa + fb; fc.show(); // 5 /6 Fraction fd = fa * fb; fd.show(); // 1/ 6 fa *= fb; fa.show(); // 1/6 } `扩展:` 单参数构造: 如果一个类型构造函数只有一个参数,则可以使用以下方法初始化 A a = 10; // 相当于 A a(10); A foo() { int x; return x; // 返回了int类型,单编译不会报错,它相当于A 临时存储区匿名变量(x) } ##5. 友元函数 可以获得对私有成员的访问权利 友元函数还可以在类内定义 有元函数就是可以访问私有成员的全局函数,不受权限限制 例子代码 #include <iostream> using namespace std; class Idata { int data; public: Idata(int data = 0):data(data) { } void show() { cout << data << endl; } friend int operator+(const Idata& a, const Idata& b); friend void operator+=(Idata& a, const Idata& b) { a.data += b.data; } }; int operator+(const Idata& a, const Idata& b) { return a.data + b.data; } int main() { Idata da(10); Idata db(100); /* 单参构造*/ Idata dc = da + db; dc.show(); // 110 da += db; da.show(); // 110 } ###友元函数,静态成员函数 ,成员函数之间的区别于联系 ----|友元函数|静态成员函数|成员函数 ----|--------|------------|-------- 访问私有数据|可以|可以(间接)|可以 受作用域和权限的控制|不受|受|受 必须通过对象调用|不用|不用|用 ##6. 输入输出运算符重载 cout << ia; 满足 L#R cout-----ostream& 不能复制 不能加const修饰 ia--------Idata类型 先去ostream类型中找一个成员函数operator(const Idata&), 肯定找不到就去全局找一个全局函数operator<<(operator& , const Idata& ) ###例子代码 #include <iostream> using namespace std; class Idata() { int data; public: Idata(int data):data(data) { } friend ostream& operator<<(ostream& os, const Idata& a) { return os<<a; //return os; } friend istream operator>>(istream& is, Idata& a) { return is >> a.data; } }; int main() { Idata da(100); Idata db(10); cout << da << endl; ci >> da >> db; cout << da << endl; cout << db << endl; } ##7. 总结二元运算符重载 L#R 先去ostream类型中找一个成员函数operator(const Idata&), 如果找不到就去全局找一个全局函数operator<<(operator& , const Idata& ) ==,+,-,*,/,+=,*=,/=,-=,%,<<,>>等等
上一篇:
08单目运算符重载/运算符重载的限制/特殊运算符重载
下一篇:
06拷贝构造/静态成员/单例模式
0
赞
40 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册