精华内容
下载资源
问答
  • 友元函数、友元类

    2017-03-07 20:13:53
    是一类需要另一类建立联系,保持调用关系,则也可以设为该类的友元类,友元可以增加代码的灵活性,提高运行效率(类型检查和数据成员和成员函数的安全性检查会消耗时间),但同样破坏了C++的封装性

    由于采用类的机制,实现了数据的封装和隐藏,类的数据成员一般设为私有类型,成员函数则为公有类型,提供与外界连接的接口,但有时需要非类成员函数频频访问类内数据成员,则将其设为该类的友元函数,简称友元,同样还有友元类,是一类需要与另一类建立联系,保持调用关系,则也可以设为该类的友元类,友元可以增加代码的灵活性,提高运行效率(类型检查和数据成员和成员函数的安全性检查会消耗时间),但同样破坏了C++的封装性,使其能够访问该类的私有成员。


    友元可以分为友元函数和友元类,友元函数又可以分为友元全局函数和友元成员函数,友元关系不可传递,单向性。友元其实破坏了C++的封装性,是对封装的补充。

    友元全局函数:

    在主函数前面声明定义时加上friend关键字,在其关联的类的关系运算符前加上此函数的声明,并加上关键字friend

    如:

    friend void display() { }

    class Person

    {

    friend void display();

    public:

    }

    友元成员函数:

    在与之关联成友元的类中要写上 如:friend void Match::printtime(Time &t);

    友元类:

    friend class A 的形式

    展开全文
  • 静态成员与友元

    2019-09-25 17:49:48
    1、类所有对象往往需要共享某个数据,所以需要静态成员,如学生类中学生总数 2、静态成员使用:如staticinttotal;//注意不能初始化 ...5、静态成员函数与联系,不与类对象联系,所以访问静态成员函数...

    1、类的所有对象往往需要共享某个数据,所以需要静态成员,如学生类中的学生总数

    2、静态成员的使用:如static int total; //注意不能初始化

    3、 初始化形式:int student::total = 0;//最好放在类的内部实现文件中,便于重用

    4、当使用对象来调用静态变量时,c++只关心对象的类型

    5、静态成员函数与类联系,不与类的对象联系,所以访问静态成员函数时,可以不需要对象。如果用对象去引用静态成员函数,只是用其类型。

    6、一个静态成员函数不和任何对象相联系,故不能对非静态成员进行默认访问!!!

    7、普通函数需要直接访问类的保护或私有数据成员的原因主要是为提高效率。

    8、友元的使用:friend 返回类型 函数名(参数列表);

    9、友元的声明的位置可在类的任何部位,即可在public又可在private protected,友元函数定义则在类的外部,一般与类的成员函数定义放在一起。

    10、一个类的成员函数可以使另一个类的友元。

    11、整个类可以使另一个类的友元,该友元称为友类。  

    转载于:https://www.cnblogs.com/hlb430/archive/2012/06/08/2613039.html

    展开全文
  • 2:虚函数允许函数调用与函数的联系在运行时才进行,称为动态联编。3:实现运行时多态的关键首先是要说明虚函数,另外,必须用类指针调用派生类的不同实现版本4:注意点:①:一个虚函数,在派生类层界面相同的...

    虚函数和多态

    1:多态性是指一个名字,多种语义;或界面相同,多种实现。

    2:虚函数允许函数调用与函数体的联系在运行时才进行,称为动态联编。

    3:实现运行时多态的关键首先是要说明虚函数,另外,必须用类指针调用派生类的不同实现版本

    4注意点:

    ①:一个虚函数,在派生类层界面相同的重载函数都保持虚特性

     ②:虚函数必须是类的成员函数

     三:不能将友元说明为虚函数,但虚函数可以是另一个类的友元

     ④:析构函数可以是虚函数,但构造函数不能是虚函数。

    5:虚函数的重载特性:

    ①:在派生类中重载基类的虚函数要求函数名、返回类型、参数个数、参数类型和顺序完全相同

     ②:如果仅仅返回类型不同,C++认为是错误重载。如果函数原型不同,仅函数名相同,丢失虚特性

    6:虚析构函数:

    ①:构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数

    ②:析构函数可以是虚的。虚析构函数用于指引 delete 运算符正确析构动态对象

    7构造函数、内联成员函数、静态成员函数不能是虚函数。

    8析构函数可以是虚函数,通常声明为虚函数。

    9:纯虚函数和抽象类:

    纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。

    二:典型代码:

    #include<iostream>
    using namespace std ;
    class  Base
    { public :       Base(char xx)  { x = xx; }
                          void who()  { cout << "Base class: " << x << "\n" ; }
       protected:    char x;
    } ;
    class  First_d : public  Base
    { public :       First_d(char xx, char yy):Base(xx)  { y = yy; }
                          void who()  { cout << "First derived class: "<< x << ", " << y << "\n" ; }
       protected:    char y;
    } ;
    class  Second_d : public  First_d
    { public :
          Second_d( char xx, char yy, char zz ) : First_d( xx, yy ) { z = zz; } 
          void who()  { cout << "Second derived class: "<< x << ", " << y << ", " << z << "\n" ; }
       protected:    char z;
    } ;
    int main()
    { Base  B_obj( 'A' ) ;   First_d F_obj( 'T', 'O' ) ;  Second_d S_obj( 'E', 'N', 'D' ) ;
       Base  * p ;
       p = & B_obj ;    p -> who() ;
       p = &F_obj ;     p -> who() ;
       p = &S_obj ;     p -> who() ;
       F_obj.who() ;
       ( ( Second_d * ) p ) -> who() ;
    }
    

    展开全文
  • C++ 面试准备【一】

    2019-09-23 19:18:05
    目录 关键字操作符 static const #define typedef using 指针引用 引用指针的区别和联系 为什么传引用比传指针安全?...空类默认成员函数 友元函数和友元类 ...不能声明为虚函数的成员函数 override和ov...

    目录
    • 关键字与操作符
      static
      const
      #define
      typedef
      using

    • 指针与引用
      引用与指针的区别和联系
      为什么传引用比传指针安全?
      野指针
      智能指针


    • 空类默认成员函数
      友元函数和友元类

    • 多态与虚函数
      C++多态性实现原理
      动态绑定
      虚函数表和虚函数指针
      纯虚函数
      override和final
      回避虚函数机制
      不能声明为虚函数的成员函数
      override和overwrite的区别


    关键字与操作符

    该部分内容包括:

    • static
    • const
    • #define
    • typedef
    • using

    指针与引用

    该部分内容包括:

    • 引用与指针的区别和联系
    • 为什么传引用比传指针安全?
    • 野指针
    • 智能指针

    引用与指针的区别和联系

    1. 指针是实体,会为其分配内存,且可以允许多级指针
    2. 引用创建时必须初始化且不可变(只能初始化一次故不用const),指针创建时无须初始化但最好初始化以防止NULL
    3. 二者自增(++)结果不同,引用是值进行自增,而指针是地址进行自增;
    4. sizeof 结果不同,sizeof 引用得到的是所指向的变量(对象)的大小,而sizeof 指针得到的是指针本身的大小
    5. 引用访问是直接访问原对象,指针则是间接访问
    6. 作为参数给函数传参不同,引用传参会比指针传参更安全,原因见下一问
    • 联系
    1. 引用的内部使用指针实现的
    2. 引用是受了限制的指针

    为什么传引用比传指针安全?

    1. 引用在创建的同时必须初始化,保证引用的对象是有效的,所以不存在NULL引用;而指针在定义的时候不必初始化,所以,指针则可以是NULL,可以在定义后面的任何地方重新赋值
    2. 引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以改变为指向另一个对象
    3. 引用的创建和销毁并不会调用类的拷贝构造函数
      因为不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,所以比指针安全。
      由于 const 指针仍然存在空指针,并且有可能产生野指针,所以还是不安全。解决方案是智能指针。

    野指针

    野指针不是NULL指针,是未初始化或者未清零的指针,它指向的内存地址不是程序员所期望的,可能指向了受限的内存。
    成因:
    1)指针变量没有被初始化
    2)指针指向的内存被释放了,但是指针没有置NULL
    3)指针超过了变量的作用范围,比如b[10],指针b+11

    介绍一下智能指针

    智能指针,将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
    智能指针就是一种栈上创建的对象,函数退出时会调用其析构函数,这个析构函数里面往往就是一堆计数之类的条件判断,如果达到某个条件,就把真正指针指向的空间给释放了。
    使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,野指针,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存。
    注意:不能将指针直接赋值给一个智能指针,一个是类,一个是指针。

    常用的智能指针

    智能指针在C++11版本之后提供,包含在头文件中,shared_ptr、unique_ptr、weak_ptr。
    在C++98中,有std::auto_ptr,但它有很多问题。 不支持复制(拷贝构造函数)和赋值(operator =),但复制或赋值的时候不会提示出错。所以可能会造成程序崩溃。

    auto_ptr<string> p1(new string ("auto") );//#1
    auto_ptr<string> p2;                         //#2
    p2 = p1;                                        //#3

    在语句#3中,p2接管string对象的所有权后,p1的所有权将被剥夺,可防止p1和p2的析构函数试图刪同—个对象;
    如果再访问p1指向的内容则会导致程序崩溃,因为p1不再指向有效的数据。std::auto_ptr 被unique_ptr代替。

    1. unique_ptr
      某个时刻只能有一个unique_ptr指向一个给定的对象。
      不支持复制和赋值,但比auto_ptr好,直接赋值会编译出错。实在想赋值的话,需要使用std::move
    2. shared_ptr
      基于引用计数的智能指针,提供所有权共享的智能指针,在最后一个指向共享对象的shared_ptr被销毁时释放共享对象。
    3. weak_ptr
      用来解决shared_ptr循环引用的问题,见参考4
      弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。
      将一个weak_ptr绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。
      一旦最后一个所指向对象的shared_ptr被销毁,所指向的对象就会被释放,即使此时有weak_ptr指向该对象,所指向的对象依然被释放。

    该部分内容包括:

    • 空类默认成员函数
    • 友元函数和友元类

    空类缺省有哪些成员函数

    1. 构造函数
    2. 析构函数
    3. 拷贝构造函数
    4. 赋值函数(operator=)

    友元函数和友元类

    友元提供了不同类的成员函数之间、类的成员函数和一般函数之间进行数据共享的机制。
    通过友元,一个不同函数或者另一个类中的成员函数可以访问类中的私有成员和保护成员。
    友元的正确使用能提高程序的运行效率,但同时也破坏了类的封装性和数据的隐藏性,导致程序可维护性变差。
    详情见参考5

    • 友元函数
      友元函数是可以访问类的私有成员的非成员函数。它是定义在类外的普通函数,不属于任何类,但是需要在类的定义中加以声明。
    friend 类型 函数名(形式参数);

    一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

    • 友元类
      友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
    friend class 类名;

    使用友元类时注意:

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

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

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


    多态与虚函数

    多态是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。
    多态包括编译时多态运行时多态,编译时多态体现在运算符重载上,运行时多态是通过继承和虚函数来体现的。
    类的继承中使用虚函数来重写(override)基类中的函数。

    在实际开发时,一般面向接口开发,操作父类指针即可。运行时父类指针指向子类对象并可访问子类同名函数,这时父类的虚函数就提供了接口。

    该部分内容包括:

    • C++多态性实现原理
    • 动态绑定
    • 纯虚函数
    • override和final
    • 回避虚函数机制
    • 不能声明为虚函数的成员函数
    • override和overwrite的区别

    C++多态性实现原理

    在继承体系下,将父类的某个函数给成虚函数(即加上virtual关键字),在派生类中对这个虚函数进行重写,利用父类的指针或引用调用虚函数。通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。对于虚函数调用来说,每一个对象内部都有一个虚表指针,在构造子类对象时,执行构造函数中进行虚表的创建和虚表指针的初始化,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用,这就是C++多态性实现的原理。

    普通函数是静态编译的,没有运行时多态。

    动态绑定与静态绑定

    静态绑定和动态绑定是C++多态性的一种特性。
    1)对象的静态类型和动态类型
    静态类型:对象在声明时采用的类型,在编译时确定
    动态类型:当前对象所指的类型,在运行期决定,对象的动态类型可变,静态类型无法更改
    2)静态绑定和动态绑定
    静态绑定:绑定的是对象的静态类型,函数依赖于对象的静态类型,在编译期确定
    动态绑定:绑定的是对象的动态类型,函数依赖于对象的动态类型,在运行期确定
    只有虚函数才使用的是动态绑定,其他的全部是静态绑定。

    何时发生动态绑定

    只有通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数,才能发生动态绑定。若使用静态对象调用虚函数,是无法发生动态绑定,这时只能调用基类的成员函数。
    详情可见参考3

    纯虚函数

    基类中为其派生类保留一个名字,以便派生类根据需要进行定义。
    包含一个纯虚函数的类被称为抽象类,比如说“动物”这样一个类不便于定义具体成员函数,其子类“长颈鹿”、“大象”等才应该定义具体的成员函数,这时候“动物”类适合定义定义为抽象类,成员函数创建为纯虚函数以提供接口。
    纯虚函数的形式如下:

    virtual returnType function() = 0;

    抽象类不可以实例化,但可以定义指针。

    虚函数的使用场景

    函数传参时,直接传基类指针,在函数中即可直接对基类指针操作,而不用考虑具体是哪个派生类,这样便于函数的封装。

    void func(Base *base){...}

    虚函数表和虚函数指针

    虚函数vtable表属于类(有点像一个类里面的staic成员变量);不同编译器的vtable存放位置不同,如gcc编译器的实现中虚函数表vtable存放在可执行文件的只读数据段。
    虚函数指针属于类的实例化对象,大小固定;vptr存放在栈中。

    override和final说明符

    C++11中可以使用override关键字来说明派生类中的虚函数以方便查错。

    void f1() const override;    // 子类虚函数重写f1

    为了拒绝在子类中重写父类的函数,可以使用final,方便查错。

    void f1() const final;          // 父类函数不允许子类重写f1

    如何回避虚函数机制

    某些情况希望对虚函数的调用不要进行动态绑定,而是强迫执行虚函数的某个特定版本。
    这时候可以使用作用域运算符::

    DerivedClass child;
    double x = child -> BaseClass::function();

    哪些类中的成员函数不能声明为虚函数

    1. 静态成员函数
    2. 内联函数
    3. 构造函数
    • 静态成员函数不能定义为虚函数
      因为静态成员函数没有this指针,并且静态成员函数可以通过类名来访问。
      又因为虚函数是放在对象的虚表里面的,同一个类中的所有对象虽然共用同一张虚表,但是类名无法找到虚表。
    • 内联函数不能定义为虚函数
      因为内联函数没有地址,而虚表里面存放的就是虚函数的地址。
    • 构造函数不能定义为虚函数
      因为虚函数是存放在对象的虚表里面,如果将构造函数定义为虚函数,则构造函数也必须存放在虚表里面,但是此时对象都还没有创建也就没有所谓的虚表。

    override和overwrite的区别

    1)override,派生类覆盖基类的虚函数,实现接口的重用,返回值类型必须相同
    特征:不同范围(基类和派生类)、函数名字相同、参数相同、基类中必须有virtual关键字(必须是虚函数)
    2)overwrite,派生类屏蔽了其同名的基类函数,返回值类型可以不同
    特征:不同范围(基类和派生类)、函数名字相同、参数不同或者参数相同且无virtual关键字
    在子类中overwrite直接覆盖掉同名成员函数,对于子类对象来说,父类的同名函数是不可见的,就无法实现父类指针或引用调用子类同名函数了。

    值得注意的是,C++中是没有overwrite这个术语的。


    参考内容

    1. 常见C++笔试面试题整理. https://mp.weixin.qq.com/s/hONnHSkR8Qk4doIK0aYHiQ
    2. C++面试基础题汇总. https://www.cnblogs.com/277223178dudu/p/10750434.html
    3. 虚函数调用的几种方式. https://www.cnblogs.com/lsgxeva/p/7692567.html
    4. weak_ptr这个智能指针有什么用. https://segmentfault.com/q/1010000004078858
    5. 【C++基础之十】友元函数和友元类. https://blog.csdn.net/m0_38126105/article/details/78757872
    6. 图说C++对象模型:对象内存布局详解. https://www.cnblogs.com/QG-whz/p/4909359.html#_label1

    转载于:https://www.cnblogs.com/lvjincheng/p/11317105.html

    展开全文
  • 编译单元:  当一个c或cpp文件在编译时,预处理器首先递归包含头文件,形成一个含有所有必要信息单个源文件,这个源文件就是一个... 如果一个函数是自由函数,那么这个函数不是类的成员函数,也不是友元函数。 ...
  • 第五章 C++程序结构 清华大学 郑 莉 本章主要内容 作用域可见性 对象生存期 数据与函数 静态成员 共享数据保护 友元 编译预处理命令 多文件结构和工程 一作用域可见性 作用域讨论是标识符有效范围可见...
  • 在学习c++基础总结了笔记,...——主席案例练习2:打印机案例4、C++面向对象模型初探5、this指针6、空指针访问成员函数7、常函数与常对象8、全局函数做友元函数9、整个类做友元类10、类模板分文件编写问题及解决11...
  • 式定义时,将如何隐式地生成成员函数以及这些成员函数的行为。读者还将通过使用对象指针,了解队列 模拟问题,扩充类方面的知识。 第13章:类继承 在面向对象编程中,继承是功能最强大的特性之一,通过继承,...
  • C++中继承

    2017-01-12 23:58:00
    目录: 继承基本概念 继承中访问控制方式 继承中构造函数和析构函数 类型兼容性原则 ...一,继承基本概念 ...use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者...
  • C++必须知道问题

    2013-09-06 16:42:05
    . 什么是常对象? 13. 静态函数存在的意义?...17. 赋值运算符和拷贝构造函数的区别与联系? 18. 在哪种情况下要调用该类的析构函数? 19. 对象间是怎样实现数据的共享的? 20. 友元关系有什么特性?
  • 式定义时,将如何隐式地生成成员函数以及这些成员函数的行为。读者还将通过使用对象指针,了解队列 模拟问题,扩充类方面的知识。 第13章:类继承 在面向对象编程中,继承是功能最强大的特性之一,通过继承,...
  • 式定义时,将如何隐式地生成成员函数以及这些成员函数的行为。读者还将通过使用对象指针,了解队列 模拟问题,扩充类方面的知识。 第13章:类继承 在面向对象编程中,继承是功能最强大的特性之一,通过继承,...
  • 式定义时,将如何隐式地生成成员函数以及这些成员函数的行为。读者还将通过使用对象指针,了解队列 模拟问题,扩充类方面的知识。 第13章:类继承 在面向对象编程中,继承是功能最强大的特性之一,通过继承,...
  • c++中继承

    2017-09-25 16:55:38
    use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数方式来实现。is-A,即继承关系,关系具有传递性。 2.继承相关概念  万事万物皆有继承这个现象,所谓
  • use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数方式来实现。is-A,即继承关系,关系具有传递性。(2) 继承相关概念万事万物皆有继承这个现象,所谓继承就是一个类继承了...
  • 类学习之进修

    2019-06-24 00:23:42
    在之前类和对象学习中,对一些概念,如数据抽象、封装、struct、this指针、访问器修改器、友元、static成员、析构和构造函数都有相对了解,在这一阶段学习之后,这些概念得到运用并且能够在自己手中得到“升华...
  • RCP法RSP法主要区别是前者采用循环渐进开发方式,原型将成为最终产品,而后者将被废弃。(√) 三、简答题 1. 软件产品特性是什么? 答: ● 软件是一种逻辑产品,具有无形性;  ● 软件产品生产...
  • 21天学通C++ (中文第五版)

    热门讨论 2010-06-23 16:57:03
    8.11.1 const指针和const成员函数 8.11.2 使用const this指针 8.12 小结 8.13 问答 8.14 作业 8.14.1 测验 8.14.2 练习 第9章 使用引用 9.1 什么是引用 9.2 将地址运算符用于引用 9.3 引用对象 9.4 空...
  • C++继承基础总结

    2018-02-26 20:28:00
    1.继承基本概念 1.类类之间关系 ...use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数方式来实现。 is-A,即继承关系,关系具有传递性。 2.继承相关...
  • C++中继承及virtual小结

    2018-12-15 11:26:10
    一、继承基础知识 ...use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数方式来实现。(和组合不同) is-A,即继承关系,关系具有传递性。 继承特点 子类拥有...
  • 8.1.3 析构函数与动态内存分配 372 8.2 实现复制构造函数 375 8.3 在变量之间共享内存 377 8.3.1 定义联合 377 8.3.2 匿名联合 379 8.3.3 类和结构中联合 379 8.4 运算符重载 379 8.4.1 实现重载...
  • 文档里留有本人扣扣、微信,运到问题可以联系, 不忽悠。 [内容简介] 本书总结了十几本C++图书及教材优点,摈弃了它们语言拖沓、层次结构混乱等缺陷,从零开始、由浅入深、层层递进、细致而又详尽地讲解C++这...
  • C++讲义及习题指导

    2010-02-16 23:10:19
    (1)C++语言支持数据封装 封装是指把对象属性和操作结合在一起,构成独立单元,它内部信息对外界是隐蔽,不允许外界直接存取对象属性,只能通过有限接口对象发生联系。类是数据封装工具,对象是封装...
  • 3.8.5 使用成员函数的算法 56 3.8.6 标准库算法 56 3.9 数学 57 3.9.1 复数 57 3.9.2 向量算术 57 3.9.3 基本数值支持 58 3.10 标准库功能 58 3.11 忠告 58 第一部分 基本功能 第4章 类型和声明 63 4.1 ...
  • 3.8.5 使用成员函数的算法 56 3.8.6 标准库算法 56 3.9 数学 57 3.9.1 复数 57 3.9.2 向量算术 57 3.9.3 基本数值支持 58 3.10 标准库功能 58 3.11 忠告 58 第一部分 基本功能 第4章 类型和声明 63 4.1 ...
  • C++程序设计语言(特别版)--源代码

    热门讨论 2012-04-23 07:33:51
    3.8.5 使用成员函数的算法 56 3.8.6 标准库算法 56 3.9 数学 57 3.9.1 复数 57 3.9.2 向量算术 57 3.9.3 基本数值支持 58 3.10 标准库功能 58 3.11 忠告 58 第一部分 基本功能 第4章 类型和声明 63 4.1 ...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

友元函数与成员函数的联系