C++中有四种强制类型转换操作符:
隐式类型转换:隐式类型转换是从小到大的转换。在数据类型上表现是少字节数据类型,转换成多字节数据类型,保证数据的完整性;在类上表现,从子类转换成父类,保证类对象功能的正常。
在同一继承体系中:
upcast(向上转换 即子类转成父类):没有问题.因为父类的行为都包含在子类中;
downcast(向下转换):有可能会出现问题,编译时可能不会发现.
下面说说常用的其它两种转型,取自 Google Chrome 的源码。
implicit_cast
template
inline To implicit_cast(From const &f) {
return f;
}
用法:
double d = 3.14;
int i = 3;
std::min(d, implicit_cast(i));
implicit_cast 相较于其它转型的好处是:
down_cast
down_cast 是在继承结构中往下转型(也就是将基类指针转换为派生类的指针,前提是基类指针指向的派生类对象,才能向下转型),这也正是down的含义,它是用来替代dynamic_cast 的,没有运行时检查,直接用static_cast 来做转型,从而提高性能。当然,使用场景也就受了限制,只有当你 100% 确定 From和To 的关系时,才能使用,否则后果自负。
template
inline To down_cast(From* f) {
if (false) {
implicit_cast(0);
}
#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only!
#endif
return static_cast(f);
}
down_cast 的实现巧妙的使用了implicit_cast ,让编译器帮助做了类型检查,而 if(false) 条件保证了最终肯定会被编译器优化掉,所以对性能没有任何影响。
#ifndef MUDUO_BASE_TYPES_H
#define MUDUO_BASE_TYPES_H
#include
#include // memset
#include
#ifndef NDEBUG
#include
#endif
///
/// The most common stuffs.(最常见的东西)
///
namespace muduo
{
using std::string;
//简化了 memset 的使用
inline void memZero(void* p, size_t n)
{
//将p中当前位置后面n个字节用0替换并返回p。
memset(p, 0, n);
}
// Taken from google-protobuf stubs/common.h
//
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: [email protected] (Kenton Varda) and others
//
// Contains basic types and utilities used by the rest of the library.
// 使用 implicit_cast作为 static_cast 或者 const_cast的安全版本
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
// a const pointer to Foo).
// When you use implicit_cast, the compiler checks that the cast is safe.
// Such explicit implicit_casts are necessary in surprisingly many
// situations where C++ demands an exact type match instead of an
// argument type convertable to a target type.
//当你使用 implicit_cast 时,编译器将检查转换是否安全
// The From type can be inferred, so the preferred syntax for using
// implicit_cast is the same as for static_cast etc.:
//
// implicit_cast(expr)
//
// implicit_cast would have been part of the C++ standard library,
// but the proposal was submitted too late. It will probably make
// its way into the language in the future.
//用于在继承关系中,子类指针转化为父类指针(即up-cast 上转型);隐式转换
//将 From 转成了 To
template
inline To implicit_cast(From const &f)
{
return f;
}
// When you upcast (that is, cast a pointer from type Foo to type
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
// always succeed. When you downcast (that is, cast a pointer from
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
// how do you know the pointer is really of type SubclassOfFoo? It
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
// when you downcast, you should use this macro. In debug mode, we
// use dynamic_cast<> to double-check the downcast is legal (we die
// if it's not). In normal mode, we do the efficient static_cast<>
// instead. Thus, it's important to test in debug mode to make sure
// the cast is legal!
// This is the only place in the code we should use dynamic_cast<>.
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
// do RTTI (eg code like this:
// if (dynamic_cast(foo)) HandleASubclass1Object(foo);
// if (dynamic_cast(foo)) HandleASubclass2Object(foo);
// You should design the code some other way not to need this.
template // use like this: down_cast(foo);
inline To down_cast(From* f) // so we only accept pointers
{
// Ensures that To is a sub-type of From *. This test is here only
// for compile-time type checking, and has no overhead in an
// optimized build at run-time, as it will be optimized away
// completely.
//下面这个if语句永远不会被执行
if (false)
{
implicit_cast(0);
}
#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only!
#endif
return static_cast(f);
}
} // namespace muduo
#endif // MUDUO_BASE_TYPES_H
总结
在程序设计中,主要是我们自己代码编写者要明确的知道当前是 down_cast 还是 up_cast , up_cast 那就使用implicit_cast ,down_cast 就用 down_cast 。