技术小记6(C++)

友元函数(friend function)
1. 什么是友元函数?
    一个类的私有数据成员通常只能由类的函数成员来访问,而友元函数可以访问类的私有数据成员,也能访问其保护成员
2. 友元函数的用处体现在哪里?
    2.1 使用友元函数可提高性能,如:用友元函数重载操作符和生成迭代器类
    2.2 用友元函数可以访问两个或多个类的私有数据,较其它方法使人们更容易理解程序的逻辑关系
3. 使用友元函数前应注意:
    3.1 类的友元函数在类作用域之外定义,但可以访问类的私有和保护成员
    3.2 尽管类定义中有友元函数原型,友元函数仍然不是成员函数
    3.3 由于友元函数不是任何类的成员函数,所以不能用句柄(对象)加点操作符来调用
    3.4 public, private, protected成员访问符与友员关系的声明无关,因此友元关系声明可在类定义的任何位置,习惯上在类定义的开始位置
    3.5 友元关系是指定的,不是获取的,如果让类B成为类A的友元类,类A必须显式声明类B为自己的友元类
    3.6 友元关系不满足对称性和传递性
    3.7 如果一个友元函数想与两个或更多类成为友元关系,在每个类中都必须声明为友元函数
4. 注:由于C++属于混合语言,常在同一个程序中采用两种函数调用且这两种函数调用往往是相反的。类C语言的调用将  

    基本数据或对象传递给函数,C++调用则是将函数(或信息)传递给对象

只要能避免使用友元函数就要避免


2.禁止对象复制,需要将相关函数声明为private且不定义,

但限制对象创建将构造函数定义为private必须定义


const 对象只能使用 const 成员。非 const 对象可以使用任一成员,但非 const 版本是一个更好的匹配。

很明显,值传递不需要const


 函数返回值采用“引用传递”的场合并不多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达


很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数

有些时候,你想使一个类成为抽象类,但刚好又没有任何纯虚函数。怎么办?

方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。


Const成员函数在声明和定义定义时都要加上const,否则被视为2个不同的函数


成员变量的初始化,类的内存的申请都会自动加入到构造函数中,析构函数同理,所以构造函数和析构函数常常不适合内联,所以一般最好不要把构造函数和析构函数的定义放到类的声明里面


内联函数在C++类中,应用最广的,应该是用来定义存取函数


1.    数组作为函数的参数时会退化为指针,除非声明为:

Voidfun(int  (&array)[12]);才会保持为声明的数组

但这样声明的话,即使是这样的参数,fun()也会不接受:

Int *arr = newint[12];

所以最好还是void fun(int arrary[], size_t size);


3.  进行类的指针比较时,编译器是按类型来取偏移地址,然后比较,所以不能去掉其类型
void *v = subj;                                               
if( ob == v ) // not equal!     

1.      一维数组会退化,二位数组不会退化,即

Int  a[2][3];

Int  **p = a;//error


placement new:

void main()

{

void *pBuffer = ::operator new[]( 5 * sizeof(CT2) );
//char* pBuffer = new char[ 5 * sizeof(CT2) ]; 无法用这种方式分配内存
CT2 *pCTBuffer = static_cast<CT2*>(pBuffer);


CT2* pT[5];
for( int i = 0; i < 5; i++ )
{
pT[i] = new (&pCTBuffer[i]) CT2(i);
}


for( int j = 0; j < 5; j++ )
{
pT[j]->Display();
}




for( int k = 4; k >= 0; k-- )
{
pT[k]->~CT2();
}


::operator delete[](pBuffer);




std::cout << "****************************" << std::endl;


{
char* buffer = new char[ 5 * sizeof(CT2) + sizeof(int) ];
CT2* pT = new (buffer) CT2[5]; //用这种方式创建对象时必须加上sizeof(int)


for( int i = 0; i < 5; i++ )
{
pT[i].~CT2();
}


delete [] buffer;
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.java的Java类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值