CCDictionary中objectForKey和valueForKey的区别

来源:互联网 发布:网络成瘾怎么办 编辑:程序博客网 时间:2024/05/14 17:48
在群里碰到一个好友问他写了如下代码,为什么打印出来结果为:#######dict count:0################(其实不一定是0,只是他的机器恰好显示为0),因此他怀疑是不是CCDictionary 不可以存放CCArray!!!(注意:CCDictionary 可以存放CCArray),本来问题不严重,这么一怀疑问题就严重了!!下面我会解释一下为什么(别看这么几行代码,但是这位好友暴露出来的问题就很多)

// 创建一个字典CCDictionary *dict = CCDictionary::create();// 创建一个数组 CCArray *array = CCArray::create();// 向数组中添加对象 array ->addObject(CCString::create("hello"));// 把刚创建的数组以键值对方式添加到字典中(如果已经有该键,则覆盖值) dict->setObject(arr, "arr");// 根据键取出字典中的数组 CCArray *temparr = (CCArray *)dict->valueForKey("arr");// 打印数组大小(会打印一个int型数字,我打印了个#######dict count:4766876################,明显的有问题) CCLOG("#######dict count:%d################",temparr->count());


那个这个好友的问题在哪呢?为什么他输出的是0,而我输出的是4766876呢?
首先我们要纠正他的怀疑,CCDictionary 可以存放CCArray!!!!why?
那我们看一下CCDictionary的添加对象成员函数setObject的声明:

void setObject(CCObject* pObject, const std::string& key);void setObject(CCObject* pObject, intptr_t key);

看到了吗,只要是CCObject都可以加入到字典中,CCArray 继承自CCObject当然也可以了!!!!所以问题不在这里,这样的怀疑会破坏力很大的!!!

那么为甚么打印结果不对呢?其实问题出在valueForKey上!!CCDictionary提供了两个获取字典值的方法valueForKey和objectForKey,我们看一下它们的声明,就知道了。

CCObject* objectForKey(const std::string& key);CCObject* objectForKey(intptr_t key);const CCString* valueForKey(const std::string& key);const CCString* valueForKey(intptr_t key);

// 看其中valueForKey(const std::string& key)的实现,调用了objectForKey,但是做指针强制转换了dynamic_cast<CCString*>

const CCString* CCDictionary::valueForKey(const std::string& key){    CCString* pStr = dynamic_cast<CCString*>(objectForKey(key));    if (pStr == NULL)    {        pStr = CCString::create("");    }    return pStr;}

// 其实你会C++,上面的理解很简单,我们看看他的官方解释
/** Get the value according to the specified string key.
     *
     * @note Be careful to use this function since it assumes the objects in the dictionary are CCString pointer.
     * @param key The string key for searching
     * @return An instance of CCString.
     * It will return an empty string if the objects aren't CCString pointer or the key wasn't found.
     * @see valueForKey(intptr_t)
     */

大致意思是:小心使用这个函数,他假设字典里的对象都是CCString对象指针(注意都是),键参数为字符串,返回一个CCString对象指针,如果对象不是CCString指针或者键不存在,将会返回一个空串。清楚+明白!!!只有你的字典里存的都是CCString对象指针的时候,你才可以在取对象的的时候用
valueForKey。

然后我们具体看看上面的valueForKey实现,他其实就是调用了objectForKey,做了指针强转为CCString类型!!!(dynamic_cast做了动态类型检查,这是在运行期的时候决定的!)

注:dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用,转换失败返回0。它依赖于RTTI信息(Run-Time Type Information,通过运行时类型信息)。百科:dynamic_cast运算符可以在执行期决定真正的类型。如果downcast(向下转换)是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果downcast(向下转换)不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。dynamic_cast的更详细信息请自行谷歌,这里不做深入介绍了。

那我这位好友的问题就解决了,因为他在字典中存放的是一个数组对象,取出来的时候使用了valueForKey是不对的,应该使用objectForKey!!!!
0 0