zoukankan      html  css  js  c++  java
  • 引领Boost(二)(Boost::Any)

     在boost中有boost::Any为我们提供了类似java或.net中的object类型,boost::Any能够代表任意类型,实现任意类型的类型安全存储以及安全的取回,常用在将不同类型的对象存储在标准容器中

    一 Boost::Any

        很多时候我们想有一种可以代表任何类型的类型,比如像纯面向对象语言java或.net中的Object类型,但是对于C++本身并没有这样一个基类,所以我们如果要解决这类问题,首先我们考虑的是使用基类的指针,这能够解决以部分问题,但是更多的我们可以求助于void*,使用void*的缺点就是丢失了类型信息和缺乏类型安全。

        幸好的是在boost中有boost::Any为我们提供了类似java或.net中的object类型,boost::Any能够代表任意类型,实现任意类型的类型安全存储以及安全的取回,常用在将不同类型的对象存储在标准容器中。

    二 源码剖析

       源码: 

    namespace boost {
      
    class bad_any_cast;
      
    class any;
      template
    <typename T> T any_cast(any &);
      template
    <typename T> T any_cast(const any &);
      template
    <typename ValueType> const ValueType * any_cast(const any *);
      template
    <typename ValueType> ValueType * any_cast(any *);
    }


       Boost::Any的实现比较简单,Any拥有一个模版构造函数,这使他可以接受任何类型的对象。真正的变量内容被封装在嵌套类类型的成员变量中,并且在嵌套类中使用typeid来记录真正的类型信息。

      1) any& swap(any& other);交换存在两个 any 对象中的值。
      2) any& operator=(const any& other);如果any实例非空,则丢弃所存放的值,并存入other值的拷贝。
      3)template<typename ValueType>  any& operator=(const ValueType& value);如果any实例非空,则丢弃所存放的值,并存入 value 的一份拷贝,value可以是任意符合any要求的类型。
      4) bool empty() const;给出any实例当前是否有值,不管是什么值。因而,当any持有一个指针时,即使该指针值为空,则 empty也返回 false 。
      5) const std::type_info& type() const;给出所存值的类型。如果 any 为空,则类型为 void.
      6) any_cast()将any类型转化为真实的类型,如果是指针返回的可能是空指针,如果非指针,则可能会抛出异常。

    三 实例

    1)简单实例以及调用常用的成员函数:

    #include <iostream>
    #include 
    <string>
    #include 
    <utility>
    #include 
    <vector>
    #include 
    "boost/any.hpp"

    class A 
    {
    public:  
        
    void some_function() 
        

            std::cout 
    << "A::some_function()\n"
        }

    }
    ;
    class B
    {
    public:  
        
    void some_function() 
        

            std::cout 
    << "B::some_function()\n"
        }

    }
    ;

    void print_any(boost::any& a)
    {  
        
    if (A* pA=boost::any_cast<A>(&a)) 
        
    {   
            pA
    ->some_function();  
        }
      
        
    else if (B* pB=boost::any_cast<B>(&a))
        
    {   
            pB
    ->some_function();  
        }
          
        
    else
        
    {   
            
    try 
            
    {     
                std::cout 
    << boost::any_cast<std::string>(a) << '\n';   
            }
       
            
    catch(boost::bad_any_cast&
            
    {     
                std::cout 
    << "Oops!\n";   
            }
      
        }

    }


    int main() 
    {  
        std::cout 
    << "Example of using any.\n\n"
        std::vector
    <boost::any> store_anything;  
        store_anything.push_back(A());  
        store_anything.push_back(B());  
        
    // 我们再来,再加一些别的东西  
        store_anything.push_back(std::string("This is fantastic! "));  
        store_anything.push_back(
    3);  
        store_anything.push_back(std::make_pair(
    true7.92));     
        std::for_each(  store_anything.begin(),  store_anything.end(),  print_any);


         std::cout 
    << "Example of using any member functions\n\n"
         boost::any a1(
    100); 
         boost::any a2(std::
    string("200"));  
         boost::any a3; 
         std::cout 
    << "a3 is "
         
    if (!a3.empty()) 
         
    {    
             std::cout 
    << "not empty\n "
         }
      
         std::cout 
    << "empty\n";  
         a1.swap(a2); 
         
    try 
         
    {   
             std::
    string s=boost::any_cast<std::string>(a1); 
             std::cout 
    << "a1 contains a string: " << s << "\n"
         }
     
         
    catch(boost::bad_any_cast& e) 
         
    {  
             std::cout 
    << "I guess a1 doesn't contain a string!\n"
         }
     
         
    if (int* p=boost::any_cast<int>(&a2)) 
         
    {  
             std::cout 
    << "a2 seems to have swapped contents with a1: "      << *<< "\n"
         }
     
         
    else
         
    {    
             std::cout 
    << "Nope, no int in a2\n"
         }
      
         
    if (typeid(int)==a2.type()) 
         
    {    
             std::cout 
    << "a2's type_info equals the type_info of int\n";  
         }


    }

    2)解决类似与map但是可以映射到各种不同的类型的问题:

    #include <iostream>
    #include 
    <string>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    "boost/any.hpp"
    class property
    {  
        boost::any value_;
        std::
    string name_;
    public:  
        property(
    const std::string& name,const boost::any& value)  
            : name_(name),value_(value) 
    {}  
        std::
    string name() const return name_; } 
        boost::any
    & value() return value_; } 
        friend 
    bool operator<(const property& lhs, const property& rhs)
        
    {return lhs.name_<rhs.name_;}
    }
    ;
    void print_names(const property& p) 

        std::cout 
    << p.name() << "\n";
    }

    int main() 
    {  
        std::cout 
    << "Example of using any for storing properties.\n";
        std::vector
    <property> properties; 
        properties.push_back(  property(
    "B"30));
        properties.push_back(  property(
    "A", std::string("Thirty something"))); 
        properties.push_back(property(
    "C"3.1415));  
        std::sort(properties.begin(),properties.end());
        std::for_each(properties.begin(),  properties.end(),  print_names);
        std::cout 
    << "\n";  
        std::cout 
    <<  boost::any_cast<std::string>(properties[0].value()) << "\n"
        std::cout 
    <<  boost::any_cast<int>(properties[1].value()) << "\n"
        std::cout 
    <<  boost::any_cast<double>(properties[2].value()) << "\n";    
    }

    四 注意

    1)Any中如果是指针,要注意指针的最后的释放,最好使用shared_ptr来管理。
    2)Any中如果是指针,如果Any.isempty()返回false,但是any所包含的指针仍可能是无效的。
    3)Any中如果是指针,则在调用any_cast()转化的过程中不会抛出异常,但是如果是一般变量或引用的话,类型不正确会抛出boost::bad_any_cast异常。

    五 参考

    1)Beyond the C++ Standard Library: An Introduction to Boost
    2)boost在线document

  • 相关阅读:
    [mysql] 删除唯一约束unique
    onethink 路由规则无效问题解决
    mysql source 乱码
    NLPIR
    词性标记集--计算所汉语
    [thinkphp] 无限极分类
    UITableViewCell在非Nib及Cell重用下设置CellStyle
    UIViewController的初始化
    转:NSString / NSData / char* 类型之间的转换
    转:苹果Xcode帮助文档阅读指南
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1934679.html
Copyright © 2011-2022 走看看