D.S.Graph_In12.12_Bound&UnboundFriendTemplate_InYin||PrimerPlusStruct

C++中模板类使用友元模板函数

问题始于学习数据结构,自己编写一个单链表,其中用到了重载输出运算符<<,我写的大约这样: template class List{ friend std::ostream& operator << (std::ostream& os,const List& slist); //…… };用vs2008可编译,但无法链接:无法解析的外部符号…… 后来上网查改为template class List{ friend std::ostream& operator << <>(std::ostream& os,const List& slist); //…… }; 就可以了。不知所以然,查了下《C++ Primer》才弄明白。 好了,进入正题: 在类模板中可以出现三种友元声明: (1)普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数。 (2)类模板或函数模板的友元声明,授予对友元所有实例的访问权。 (3)只授予对类模板或函数模板的特定实例的访问权的友元声明。 要注意的是,友元函数并非成员函数,是改变了它对类成员的访问权限。 (1)没有什么好说的,如: template class A{ friend void fun(); //… }; 此例中fun可访问A任意类实例中的私有和保护成员 (2) template class A{ template friend void fun(T u); //… }; 这时友元使用与类不同的模板形参,T可以是任意合法标志符,友元函数可以访问A类的任何类实例的数据,即不论A的形参是int,double或其他都可以。 (3) template class A{ friend void fun(T u); //… }; 此时fun只有访问类中特定实例的数据。换句话说,此时具有相同模板实参的fun函数与A类才是友元关系。即假如调用fun时其模板实参为int,则它只具有A的访问权限。当然friend void fun(T u);中<>中的T可以是任意类型,比如int,double等 回到原问题,按(3)可改为: template class List{ friend std::ostream& operator << (std::ostream& os,const List& slist); //…… }; 按(2)可改为: template class List{ template friend std::ostream& operator << (std::ostream& os,const List& slist); //…… }; 在这里其实两者实现的最终效果一样的,因为调用输出运算符时需要访问的类实例的对象是它本身,所以形参T在第一种改法中一定匹配。 对类建立友元函数很容易。但是迁移到模板上却容易出现让人摸不着头脑的连接错误。 层次不够,不做分析,单纯介绍两种为类模板定义友元函数的方法 1 封闭型 template< typename T > class MyClass { friend void function( MyClass< T > &arg ) { } }; 要点:友元函数定义在模板体内。 2 开放型 template< typename T > class MyClass { template< typename C > friend void function( MyClass< C > &arg ); }; template< typename C > void function( MyClass< C > &arg ) { } 要点:模板体内要另建模板。 3 告诉编译器声明的设个是模板 #include using namespace std; template < typename T > class A { friend ostream &operator<< < T >( ostream &, const A< T > & ); }; template < typename T > ostream &operator<< ( ostream &output, const A< T > &a ) { output << “重载成功” << endl; return output; } int main() { A< int > a; cout << a; } 要点:显示地在重载的运算符或者函数后面加上模板声明< T >,告诉编译器友元函数是一个类型一致的模板。 建议: 如果希望使用函数与模板特化的类型相对应,则使用方法3(模板显示声明) 如果希望使用函数与模板特化的类型相独立,则使用方法2(二重模板) 简短的内联函数使用方法1 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/squarereal/archive/2009/09/23/4579950.aspx


C/C++ 中访问结构体成员的方法

先看例子: 1#include 2void main(){ 3 typedef struct { 4 int int_field; 5 char char_field; 6 } my_struct; 7 my_struct my_s; 8 my_s.int_field=3; //结构运算符访问结构成员 9 my_struct *s; 10 s=(my_struct *)malloc (sizeof(my_struct)); 11 s->int_field=4; 12 s->char_field=’a’; 13 (*s).int_field=6; 14 } 访问结构体成员的运算符有两种,一种是“.”即结构运算符,另一种是“->”即结构指针运算符。 结构运算符是通过结构变量名访问结构体成员的(例如例子的第8行),而结构指针运算符是通过指向结构的指针访问结构成员的(例如第11及12行)。 还可以用指针和结构运算符来访问结构(如第13行),其中(*s)中的圆括号不可以省去 平时看简单例子看惯的缘故,本来以为很简单的知识。可是正到了项目上遇到了就有中把握不住的感觉,还是由于看的少的原因,所以不要只停留在理论的基础上。还是看项目源代码: 。。。。 。。。。 1. enum { LIGHT_INDEX_BACKLIGHT = 0, LIGHT_INDEX_KEYBOARD = 1, LIGHT_INDEX_BUTTONS = 2, LIGHT_INDEX_BATTERY = 3, LIGHT_INDEX_NOTIFICATIONS = 4, LIGHT_INDEX_ATTENTION = 5, LIGHT_INDEX_BLUETOOTH = 6, LIGHT_INDEX_WIFI = 7, LIGHT_COUNT }; 2. struct Devices { light_device_t lights[LIGHT_COUNT]; }; 。 。 。 。 。 。 static jint init_native(JNIEnv \env, jobject clazz) { int err; hw_module_t* module; Devices devices; devices = (Devices)malloc(sizeof(Devices)); err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); if (err == 0) { 3. devices->lights[LIGHT_INDEX_BACKLIGHT] = get_device(module, LIGHT_ID_BACKLIGHT); devices->lights[LIGHT_INDEX_KEYBOARD] = get_device(module, LIGHT_ID_KEYBOARD); devices->lights[LIGHT_INDEX_BUTTONS] = get_device(module, LIGHT_ID_BUTTONS); 。 。 。 。 。 。 } } 其中1 2 两处在上一篇 “C 中枚举(项目里遇到的)例子“ 中介绍过了。 3处 devices 是一个指向Devices型(结构体)的指针,devices->lights[LIGHT_INDEX_BACKLIGHT]即是访问到了Devices成员lights的第一个元素。 也无非就这么三种用法,熟悉了以后项目再遇到就很简单!

————-C++中结构体与类的区别(struct与class的区别){z}

C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能。 struct能包含成员函数吗? 能! struct能继承吗? 能!! struct能实现多态吗? 能!!! 既然这些它都能实现,那它和class还能有什么区别? 最本质的一个区别就是默认的访问控制: 默认的继承访问权限 struct是public的,class是private的。 你可以写如下的代码: struct A { char a; }; struct B : A { char b; }; 这个时候B是public继承A的。 如果都将上面的struct改成class,那么B是private继承A的。这就是默认的继承访问权限。 所以我们在平时写类继承的时候,通常会这样写: class B : public A 就是为了指明是public继承,而不是用默认的private继承。 当然,到底默认是public继承还是private继承,取决于子类而不是基类。 我的意思是,struct可以继承class,同样class也可以继承struct,那么默认的继承访问权限是看子类到底是用的struct还是class。如下: struct A{};class B : A{}; //private继承 struct C : B{}; //public继承 struct作为数据结构的实现体,它默认的数据访问控制是public的,而class作为对象的实现体,它默认的成员变量访问控制是private的 我依旧强调struct是一种数据结构的实现体,虽然它是可以像class一样的用。我依旧将struct里的变量叫数据,class内的变量叫成员,虽然它们并无区别。 到底是用struct还是class,完全看个人的喜好,你可以将程序里所有的class全部替换成struct,它依旧可以很正常的运行。但我给出的最好建议,还是:当你觉得你要做的更像是一种数据结构的话,那么用struct,如果你要做的更像是一种对象的话,那么用class。 当然,我在这里还要强调一点的就是,对于访问控制,应该在程序里明确的指出,而不是依靠默认,这是一个良好的习惯,也让你的代码更具可读性。 说到这里,很多了解的人或许都认为这个话题可以结束了,因为他们知道struct和class的“唯一”区别就是访问控制。很多文献上也确实只提到这一个区别。 但我上面却没有用“唯一”,而是说的“最本质”,那是因为,它们确实还有另一个区别,虽然那个区别我们平时可能很少涉及。 那就是:“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。这一点在Stanley B.Lippman写的Inside the C++ Object Model有过说明。 问题讨论到这里,基本上应该可以结束了。但有人曾说过,他还发现过其他的“区别”,那么,让我们来看看,这到底是不是又一个区别。还是上面所说的,C++中的struct是对C中的struct的扩充,既然是扩充,那么它就要兼容过去C中struct应有的所有特性。例如你可以这样写: struct A //定义一个struct { char c1; int n2; double db3; }; A a={‘p’, 7, 3.1415926}; //定义时直接赋值 也就是说struct可以在定义的时候用{}赋初值。那么问题来了,class行不行呢?将上面的struct改成class,试试看。报错!噢~于是那人跳出来说,他又找到了一个区别。我们仔细看看,这真的又是一个区别吗? 你试着向上面的struct中加入一个构造函数(或虚函数),你会发现什么? 对,struct也不能用{}赋初值了 的确,以{}的方式来赋初值,只是用一个初始化列表来对数据进行按顺序的初始化,如上面如果写成A a={‘p’,7};则c1,n2被初始化,而db3没有。这样简单的copy操作,只能发生在简单的数据结构上,而不应该放在对象上。加入一个构造函数或是一个虚函数会使struct更体现出一种对象的特性,而使此{}操作不再有效。 事实上,是因为加入这样的函数,使得类的内部结构发生了变化。而加入一个普通的成员函数呢?你会发现{}依旧可用。其实你可以将普通的函数理解成对数据结构的一种算法,这并不打破它数据结构的特性。 那么,看到这里,我们发现即使是struct想用{}来赋初值,它也必须满足很多的约束条件,这些条件实际上就是让struct更体现出一种数据机构而不是类的特性。 那为什么我们在上面仅仅将struct改成class,{}就不能用了呢? 其实问题恰巧是我们之前所讲的——访问控制!你看看,我们忘记了什么?对,将struct改成class的时候,访问控制由public变为private了,那当然就不能用{}来赋初值了。加上一个public,你会发现,class也是能用{}的,和struct毫无区别!!! 做个总结,从上面的区别,我们可以看出,struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。 [转]声明/感谢: http://blog.sina.com.cn/s/blog_7c2c21230100svc3.htmlhttp://blog.csdn.net/gengyichao/article/details/6542233 http://blog.csdn.net/xocoder/article/details/8484890

(っ•̀ω•́)っ✎⁾⁾ 坚持技术学习、内容输出与分享,您的支持将鼓励我继续创作!(*/ω\*)
( • ̀ω•́ )✧如有疑问或需要技术讨论,请留言或发邮件到 aclearzhang@qq.com.(*・ω< ) 
  • 本文作者:: AClearZhang
  • 本文链接:: 367.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!