effective c++若不想使用编译器自动生成的函数,就应该明确拒绝
2015-09-09 20:42
603 查看
友元函数:
友元函数只是一个普通函数,并不是该类的类成员函数,它可以在任何地方调用,友元函数中通过对象名来访问该类的私有或保护成员。
友元类的声明在该类的声明中,而实现在该类外。
友元关系没有继承性
假如类B是类A的友元,类C继承于类A,那么友元类B是没办法直接访问类C的私有或保护成员。
友元关系没有传递性
加入类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。
维基百科上综合的例子
初始化时调用的方法
如果不希望有两个一模一样的实例,那么需要把copy构造函数和copy assignment声明为私有化,并且,仅仅做出声明,并不定义出来。如果友元函数调用,会产生一个链接错误
或者这样,可以提前产生编译错误,避免到达链接阶段
参考:
https://zh.wikipedia.org/wiki/%E5%8F%8B%E5%85%83%E5%87%BD%E6%95%B0
/article/1340661.html
友元函数只是一个普通函数,并不是该类的类成员函数,它可以在任何地方调用,友元函数中通过对象名来访问该类的私有或保护成员。
class A { public: A(int _a):a(_a){}; friend int getA_a(A &_classA);//友元函数 private: int a; }; int getA_a(A &_classA) { return _classA.a;//通过对象名访问私有变量 }
友元类的声明在该类的声明中,而实现在该类外。
class B { public: B(int _b):b(_b){}; friend class C;//声明友元类C private: int b; }; class C//实现友元类C { public: int getB_b(B _classB){ return _classB.b;//访问友元类B的私有成员 }; };
友元关系没有继承性
假如类B是类A的友元,类C继承于类A,那么友元类B是没办法直接访问类C的私有或保护成员。
友元关系没有传递性
加入类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。
维基百科上综合的例子
#include <iostream> using namespace std; class Bezaa; // Forward declaration of class Bezaa in order for example to compile. class Aazaa { private: int a; public: Aazaa() { a = 0; } void show(Aazaa& x, Bezaa& y); friend void ::show(Aazaa& x, Bezaa& y); // declaration of global friend }; class Bezaa { private: int b; public: Bezaa() { b = 6; } friend void ::show(Aazaa& x, Bezaa& y); // declaration of global friend friend void Aazaa::show(Aazaa& x, Bezaa& y); // declaration of friend from other class }; // Definition of a member function of Aazaa; this member is a friend of Bezaa void Aazaa::show(Aazaa& x, Bezaa& y) { cout << "Show via function member of Aazaa" << endl; cout << "Aazaa::a = " << x.a << endl; cout << "Bezaa::b = " << y.b << endl; } // Friend for Aazaa and Bezaa, definition of global function void show(Aazaa& x, Bezaa& y) { cout << "Show via global function" << endl; cout << "Aazaa::a = " << x.a << endl; cout << "Bezaa::b = " << y.b << endl; } int main() { Aazaa a; Bezaa b; show(a,b); a.show(a,b); }
初始化时调用的方法
#include <iostream> #include<cstdio> #include<cstring> #include<effective_c.h> using namespace std; class TextBlock { public: TextBlock(){cout << "init" << endl;}; //private: TextBlock(const TextBlock &){cout << "copy" << endl;}; TextBlock& operator=(const TextBlock&){cout << " = " << endl;}; }; int main() { TextBlock a; //直接定义a,调用构造函数 TextBlock b(a); //用a初始化b调用copy构造函数 TextBlock c = a; //用a等号初始化c也是调用copy构造函数 c = a; //这时调用copy assignment }
如果不希望有两个一模一样的实例,那么需要把copy构造函数和copy assignment声明为私有化,并且,仅仅做出声明,并不定义出来。如果友元函数调用,会产生一个链接错误
class TextBlock { public: TextBlock(){}; //需要手动定义构造函数,以免无法实例化 private: TextBlock(const TextBlock &); TextBlock& operator=(const TextBlock&); };
class TextBlock { public: TextBlock(){}; friend void ::show(); private: TextBlock(const TextBlock &); TextBlock& operator=(const TextBlock&); }; void show() { TextBlock a,b; a = b; //link error }
或者这样,可以提前产生编译错误,避免到达链接阶段
class Uncopyable { protected: Uncopyable(){}; private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); }; class TextBlock:private Uncopyable { //class 不再声明copy构造函数或者copy assignment便好 }; int main() { TextBlock a; }
参考:
https://zh.wikipedia.org/wiki/%E5%8F%8B%E5%85%83%E5%87%BD%E6%95%B0
/article/1340661.html
相关文章推荐
- C++内存管理
- 国家模式c++
- 编程基础——C/C++,Java,ObjC讨论回调模式
- 我的C++学习心得
- c++机试整理
- C++ string string string string string string string string string string
- 第二周 项目1-C/C++语言中函数参数传递的三种方式
- C++函数调用之thiscall
- 第2周项目1-C/C++语言中函数参数传递的三种方式
- 项目11.1分离各位数
- C++用法的学习心得
- 最简单C语言的扫雷地图(不是游戏)
- C++用法及学习心得
- Ubuntu Eclipse for C++ 11
- 【C++学习笔记】const的用法
- 深入学习C++中的函数概念
- 求集合/字符串中的所有组合 (C语言)
- C++条件及循环语句的综合运用实例
- 重新认识二级指针(Pointers to Pointers)
- C++用法的学习心得