C++中的friend函数详细解析(二)

一.设计模式

  1. 单例模式(类只能生成一个对象)

  2. 屏蔽构造函数,拷贝构造函数(放在private中 类外无法访问),此时类外就无法看到这两个函数了 也就无法生成对象了 类就没有意义了

  3. 类中给出一个接口(getInstance) 生成唯一对象 返回值为类类型的指针或引用(不生成其他对象) 如果为类类型返回 则会有临时对象产生 此时就不叫单例模式了

①返回值不能返回类类型(会有临时对象产生)

②这个接口一定要不依赖对象(因为这个接口是要生成对象的 如果依赖对象 则无法生成对象) 因此要加static关键字

代码如下:

class SingleTon
{
public:
       static SingleTon* getInstance()//类中给出一个接口getInstance生成唯一对象返回值为类类型的指针或引用 同时这个接口不依赖对象因此加上static的关键字
     {
              return &single;
    }

private:
          SingleTon(){};//屏蔽构造函数(防止生成新对象)
          SingleTon(const SingleTon&);//屏蔽拷贝构造函数(防止生成新对象)
          static SingleTon single;
};
SingleTon SingleTon::single;//static修饰的成员要在类外初始化
int main()
{

   SingleTon* psingle1 = SingleTon::getInstance();

   SingleTon* psingle2 = SingleTon::getInstance();

   SingleTon* psingle3 = SingleTon::getInstance();

   SingleTon* psingle4 = SingleTon::getInstance();

    return 0;
}

线程安全问题

C++中的friend函数详细解析(二)
  1. 此时线程不安全则要加锁
class SingleTon
{
public:
      static SingleTon* getInstance()
     {
             //lock();
            if (psingle == NULL)
           {
                  psingle = new SingleTon();
          }
         //unlock();
       return psingle;
}

此时A线程执行完了 加锁解锁后 B线程才能执行 但效率很低 不管对象是否存在都会加锁解锁

  1. 双重锁机制的单例模式

当有对象生成的时候 直接返回对象 就不用加锁解锁了

在main函数之前就生成对象就不存在线程安全的问题了 因为线程在main中才执行

代码如下:

class SingleTon
{
public:
         static SingleTon* getInstance()
        {
                if (psingle == NULL)//当有对象生成的时候 直接返回对象
                {
                        //lock();
                       if (psingle == NULL)
                       {
                              psingle = new SingleTon();
                      }
                    //unlock();
       }
    return psingle;
}

private:
        SingleTon(){}
         SingleTon(const SingleTon&);
         static SingleTon* psingle;//指向对象的指针 static修饰的并不属于对象 属于类作用域

};
SingleTon* SingleTon::psingle = NULL;

二.友元函数

C++中,我们使用类对数据进行了隐藏和封装,类的数据成员一般都定义为私有成员,成员函数一般都定义为公有的,以此提供类与外界的通讯接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

友元类 :将外界的某个类在本类别的定义中说明为友元,那么外界的类就成为本类的”朋友”,那个类就可以访问本类的私有数据了。友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。

当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:

friend class 类名;

其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

例如,以下语句说明类B是类A的友元类:

class A
       {
              ...

       public:

              friend class B;

              ...

       };

经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

使用友元类时注意:

(1) 友元关系不能被继承。

(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

《windows环境多线程编程原理与应用》中解释:

如果将类的封装比喻成一堵墙的话,那么友元机制就像墙上了开了一个门,那些得

到允许的类或函数允许通过这个门访问一般的类或者函数无法访问的私有属性和方

法。友元机制使类的封装性得到消弱,所以使用时一定要慎重。

https://www.pianshen.com/article/7773114476/

友元关系有三种:

  1. 函数友元 (cdecal)
  2. 类友元 (thiscall)
  3. 类成员方法的友元

只有你赋予某个类为你的友元时,那个类才有访问你的私有数据的权利。说明一个函数为一个类的友元函数则该函数可以访问此类的私有数据和方法。定义方法是在类的定义中,在函数名前加上关键字friend.

友元函数的优缺点:

优点:打破了封装性 通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为public(共用的),然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它,c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作,避免把类成员全部设置成public,最大限度的保护数据成员的安全。

缺点:友元能够使得普通函数直接访问类的保护数据,避免了类成员函数的频繁调用,可以节约处理器开销,提高程序的效率,但所矛盾的是,即使是最大限度大保护,同样也破坏了类的封装特性,这即是友元的缺点,在现在cpu速度越来越快的今天我们并不推荐使用它,但它作为c++一个必要的知识点,一个完整的组成部分,我们还是需要讨论一下的。 在类里声明一个普通数学,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。

因此建议:能不用友元就不用友元 不得不用的时候在用友元。

Original: https://www.cnblogs.com/sggggr/p/15693581.html
Author: sgggr
Title: C++中的friend函数详细解析(二)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/535566/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • EclipseC++学习笔记-7 汉化

    1、复制https://download.eclipse.org/technology/babel/update-site/latest/ 注意要和版本保持一致,如果版本不对安装之…

    C++ 2023年5月29日
    065
  • vscode c++ 编译生成后,调试时无法命中断点

    1 //test.cpp 2 #include 3 int g_var = 0; 4 void print_line(char *str) 5 { 6 if (str != NUL…

    C++ 2023年5月29日
    065
  • [C++] 引用类型&

    引用的方法: 类型 &引用名 = 变量名; 例如: int a = 5; int &b = a; 引用的规则: 1、引用被创建的同时必须被初始化 2、无null引用…

    C++ 2023年5月29日
    058
  • C++ 创建静态链接库和动态链接库

    上篇文章演示了如恶化使用C++ 编译的静态链接库和动态链接库,本篇文章主要介绍如何创建静态链接库和动态链接库,本文使用的工具是visual studio 2019 企业版,需要安装…

    C++ 2023年5月29日
    056
  • C++ CRTP

    CRTP 英:The curiously recurring template pattern (CRTP) is a C++ idiom in which a class X d…

    C++ 2023年5月29日
    090
  • 使用Visual Leak Detector for Visual C++ 捕捉内存泄露

    1、下载vlc 2、创建应用并配置 c/c++ -> General -> Additional Include Directories = C:\Program Fi…

    C++ 2023年5月29日
    048
  • C++11 静态断言 static_assert

    我们知道,C++现有的标准中就有assert、#error两个方法是用来检查错误的,除此而外还有一些第三方的静态断言实现。 assert是运行期断言,它用来发现运行期间的错误,不能…

    C++ 2023年5月29日
    046
  • (筆記) 如何讀取binary file某個byte的值? (C/C++) (C)

    Abstract通常公司為了保護其智慧財產權,會自己定義檔案格式,其header區會定義每個byte各代表某項資訊,所以常常需要直接對binary檔的某byte直接進行讀取。 In…

    C++ 2023年5月29日
    054
  • WIN部分程序调用VS C++库导致提示报错R6034解决方法

    最近电脑上的部分软件运行的时候有时候会报错R6034,猜测可能是软件安装冲突导致 可能是因为软件在调用VS C++runtime error库的dll文件的时候找不到或者找到了错误…

    C++ 2023年5月29日
    081
  • 从OSG源码学习C++之ArgumentParser

    待续 posted @2020-09-05 07:09 焦涛 阅读(409 ) 评论() 编辑 Original: https://www.cnblogs.com/Joetao/a…

    C++ 2023年5月29日
    059
  • C++11 列表初始化

    在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于…

    C++ 2023年5月29日
    053
  • Fixed width integer types (since C++11)

    越界问题非常频繁地困扰着开发人员 CPP常用的类型定义不能体现数据的bit位数,让开发人员非常抓狂,相信很多人都遇到过,当判定一个数值是否越界时候,一定是先去网上查表, 但是数据类…

    C++ 2023年5月29日
    073
  • c++ lambda捕获this 导致多线程下类释放后还在使用的错误

    但是需要注意的是,这里捕获this,不是以一种拷贝的方式,更像是一种引用(或者别名,描述可能不准确),当在外面这个类的生命周期结束时,lambda内部还在调用这个类的成员函数,那么…

    C++ 2023年5月29日
    053
  • c++ win32 遍历进程列表

    使用 CreateToolhelp32Snapshot #include #include #include #include int main() { HANDLE hSnap …

    C++ 2023年5月29日
    065
  • Using WebAssembly threads from C, C++ and Rust

    Learn how to bring multithreaded applications written in other languages to WebAssembly. J…

    C++ 2023年5月29日
    068
  • C++ std::ofstream 和 std::ifstream

    简介 C++中对文件进行读写的。 使用Demo #include #include #include <string> #include <string.h&gt…

    C++ 2023年5月29日
    038
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球