C++Primer_Chap19_特殊工具与技术_List567_嵌套类、union、局部类_笔记

5 嵌套类

  一个类定义在另一个类的内部,前者称为嵌套类(nested class)嵌套类型(nested type)。嵌套类常用于定义作为实现部分的类。

class TextQuery {
public:
    class QueryResult;    
};

class TextQuery::QuertResult {
    friend std::ostream& print( std::ostream&, const QueryResult&)'
public:
    QueryResult(std::string,
                std::shared_ptr>,
                std::shared_ptr>>);
};

TextQuery::QueryResult::QueryResult(string s,
                shared_ptr> p,
                shared_ptr>> f) :
        sought(s), lines(p), file(f) {  }

TextQuery::QueryResult
TextQuery::query(const string &sought) const
{
    static shared_ptr> nodata(new set);
    auto loc = wm.find(sought);
    if(loc == wm.end())
        return QueryResult(sought, nodata, file);
    else
        return QueryResult(sought, loc->second, file);
}

int TextQuery::QueryResult::static_mem = 1024;

  嵌套类 是一个独立的类,与外层类基本没什么关系。特别是,外层类的对象和嵌套类的对象是相互独立的。在嵌套类的对象中不包含任何外层类定义的成员。在外层类的对象也不包含任何嵌套类定义的成员。

  嵌套类的名字在外层类作用域中是可见的,在外层类作用域之外是不可见的。

 6 unoin

  C++早起版本规定,在union中不能含有定义了构造构造或者拷贝成员的类类型成员。C++11标准取消了这个限制。不过,如果union的成员类型定义了自己的构造函数和/或拷贝控制成员,则该union的用法会复杂很多。

  当union包含的是内置类型的成员时,编译器将按照成员的次序依次合成默认构造函数或拷贝控制成员。但如果union含有类类型的成员,并且该类型自定义了默认构造函数或拷贝控制成员,则编译器将为union合成对应的版本并将其声明为delete。

  例如,string类定义了5个拷贝控制成员以及一个默认构造函数。如果union含有string类型的成员,并且没有自定义默认构造函数或某个拷贝控制成员,则编译器将合成缺少的成员并将其声明为delete的。如果在某各类中含有一个union成员,并且该union含有删除的拷贝控制成员,则类与之对应的拷贝控制操作也应该是删除的。

使用类管理union成员

  对于union来说,要想构造或销毁类类型的成员必须执行非常复杂的操作,因此我们通常把含有类类型成员的union内嵌到另一个类当中,这个类可以管理并控制与union的类类型成员有关的状态转换。

class Token {
public:
    Token() : tok(INT), ival(0) { }
    Token(const Token &t) : tok(t.tok) { copyUnion(t); }
    Token &operator=(const Token&);
    ~Token()
    {
        if( tok == STR)
            sval.~string();
    }
    Token &operator=(const std::string&);
    Token &operator=(char);
    Token &operator=(int);
    Token &operator=(double);

private:
    enum {INT, CHAR, DBL, STR} tok;    //判别式
    union {
        char         cval;
        int          ival;
        double       dval;
        std::string  sval;
    };
    void copyUnion(const Token&);
};

管理判别式并销毁string

Token &Token::operator=(int i)
{
    if( tok == STR )
        sval.~string();
    ival = i;
    tok = INT;
    return *this;
}

Token &Token::operator=(const std::string &s)
{
    if( tok == STR )
        sval = s;
    else
        new(&sval) string(s);
    tok = STR;
    return *this;
}

管理需要拷贝控制的联合成员

void Token::copyUnion(const Token &t)
{
    switch(t.tok){
        case Token::INT :
            ival = t.ival;
            break;
        case Token::CHAR :
            cval = t.cval;
            break;
        case Token::DBL :
            dval = t.dval;
            break;
        case Token::STR :
            new(&sval) string(t.sval);
            break;
    }
}
Token &Token::operator=(const Token &t)
{
    if(tok == STR && t.tok != STR)
        sval.~string();
    if(tok == STR && t.tok == STR)
        sval = t.sval;
    else
        copyUnion(t);
    tok = t.tok;
    return *this;    
}

7 局部类

  类定义在某个函数内部是,我们称其为局部类(local class)。局部类的所有成员(包括函数在内)都必须完整的定义在类的内部。局部类不允许声明静态数据成员。

  • 局部类不能使用函数作用域中的变量,只能访问外层作用域定义的类型名、静态变量以及枚举成员
  • 常规的访问保护规则对局部类同样使用

嵌套的局部类

  可以在局部类内部在嵌套一个类。嵌套类的定义可以出现在局部类之外,但必须定义在于局部类相同的作用域中。局部类内的嵌套类也是一个局部类,必须遵循局部类的各种规定:嵌套类的所有成员必须定义在嵌套类的内部

你可能感兴趣的:(C++)