友元,异常小记



  • 文中的P多少页是指c++ primer plus的第几页

    友元,异常和其他

    1.友元

    • 类并非只能拥有友元函数,也可以将类作为友元。这种情况下,友元类的所有方法都可以访问原始类的私有成员和保护成员
    • friend class Remote使Remote成为友元类。友元声明可以位于公有,私有或保护部分,其所在的位置无关紧要
    • 友元成员函数:如何仅让特定的类成员成为另一个类的友元?为了避免声明时的依赖循环,这里使用前向声明比较好-----详见P607
    • 其他友元关系:两个类互为友元
    • 共同的友元:需要使用友元的另一种情况是,函数要访问两个类的私有数据。----详见P610,有时将函数作为两个类的友元更合理

    2.嵌套类

    • c++中可以把类声明放在另一个类中。在另一个类中被声明的类被称为嵌套类,它通过提供新的类型作用域来避免名称混乱;包含类的成员函数可以创建和使用被嵌套类的对象;而仅当声明位于公有部分,才能在包含类的外面使用嵌套类,而且必须使用作用域解析运算符
    • 包含意味着将类对象作为另一个类的成员,而对类嵌套不创建类成员,而是定义了一种类型,该类型仅在包含嵌套声明的类中有效
    • 对类进行嵌套通常是为了帮助实现另一个类,并避免命名冲突
    • 嵌套类和访问权限:
      • 作用域:如果嵌套类是在另一个类的私有部分声明的,则只有后者知道它;如果嵌套类是在另一个类的保护部分声明的,则它对于后者来说是可见的,但对于外部世界则是不可见的,然而,在这种情况中,派生类将知道嵌套类,并可以直接创建这种类型的对象;如果嵌套类是在另一个类的共有部分声明的,则允许后者,后者的派生类以及外部世界使用它,因为它是公有的,但在外部世界使用时必须使用类限定符
      • 访问控制:对嵌套类访问权的控制规则与对常规类相同

    3.异常

    • 调用abort(),原型位于头文件cstdlib中,但此方法是否刷新缓存区不清楚,而用exit()将刷新文件缓存区,但不显示消息
    • 返回错误码:即使用函数的返回值来指出问题,典型的比如bool函数
    • 异常机制:异常提供了将控制权从程序的一部分传递到另一部分的途径
    • 对异常的处理有3个组成部分:-----示例详见P619
      • 引发异常
      • 使用处理程序捕获异常
      • 使用try块
    • 如果try块中的某条语句导致异常被引发,则后面的catch块将对异常进行处理
    • 将对象用作异常类型:通常,引发异常的函数将传递一个对象。这样做的优点之一是可以使用不同的异常类型来区分不同的函数在不同情况下引发的异常。另外,对象可以携带信息,程序员可以根据这些信息来确定引发异常的原因。同时,catch块可根据这些信息来决定采取什么样的措施------示例详见P622
    • 异常规范和c++11:推荐是不要使用异常规范这项功能;但c++11确实支持一种特殊的异常规范:可以使用noexcept指出函数不会引发异常
    • 栈解退:---详见P625,较复杂 这里有很重要的一点:程序进行栈解退以回到能够捕获异常的地方时,将释放栈中的自动存储型变量。如果变量是类对象,将为该对象调用析构函数;与此同时,重新引发的异常将被传递给main(),在该函数中,合适的catch块将捕获它并对其进行处理
    • 虽然throw-catch机制类似于函数参数和函数返回机制,但还是有些不同之处。其中之一是函数中的返回语句将控制权返回到调用它的函数,而throw语句将控制权向上返回到第一个这样的函数:包含能够捕获相应异常的try-catch组合; 另一个不同之处是引发异常时编译器总是创建一个临时拷贝,即使异常规范和catch块中指定的是引用
    • exception类:exception头文件定义了exception类。c++可以把它用作其他异常类的基类。代码可以引发exception异常,也可以将exception类用作基类
    • 有关exception类还有一些更细致的类----详见P631
    • 异常,类与继承见P635
    • 有关异常的注意事项:首先,通常应在程序设计时就加入异常处理功能,而不是以后再添加,但这也会带来麻烦。

    4.RTTI---运行阶段类型识别

    • c++有3个支持RTTI的元素

      • 如果可能的话,dynamic_cast运算符将使用一个指向基类的指针来生成一个指向派生类的指针;否则,该运算符返回0---空指针
      • typeid运算符返回一个指出对象的类型的值
      • type_info结构存储了有关特定类型的信息
    • 只能讲RTTI用于包含虚函数的类层次结构,原因在于只有对于这种类层次结构,才应该将派生对象的地址赋给基类指针------------一定要记住,RTTI只适用于包含虚函数的类

      • dynamic_cast运算符是最常用的RTTI组件,它不能回答“指针指向的是哪类对象”这样的问题,但能够回答“是否可以安全将对象的地址赋给特定类型的指针”
        //基本语法
        Superb * pm = dynamic_cast<Superb *>(pg);
        这里若指针pg的类型可以被安全地转化为Superb*,则运算符将返回对象的地址,否则返回一个空指针
        
      • typeid运算符和type_info类:typeid运算符使得能够确定2个对象是否为同种类型。它可以接受两种参数:类名和结果为对象的表达式。typeid运算符返回一个type_info对象的引用,其中,type_info是在头文件typeinfo中定义的一个类。type_info类重载了==和!=运算符,以便可以使用它们来比较类型
        typeid(Magnificent) ==typeid(*pg)
        若pg是一个空指针,程序将引发bad_typeid异常
        

 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

Looks like your connection to Dian was lost, please wait while we try to reconnect.