C++;相当于java';s实例 < C++ >代码> > > p> >使用: if(NewType* v = dynamic_cast<NewType*>(old)) { // old was safely casted to NewType v->doSomething(); } if(NewType*v=dynamic_cast(旧)){ //旧的铸成了新的 v->doSomething(); }
这要求编译器启用rtti支持 编辑: 我对这个答案有一些好的评论 每次你需要使用动态投射(或instanceof)时,你最好问问自己这是否是必要的。这通常是设计拙劣的标志 典型的解决方法是将您要检查的类的特殊行为放入基类上的虚拟函数中,或者可能引入类似的方法,在这种方法中,您可以在不更改接口的情况下为子类引入特定行为(当然,除了添加访问者接受接口) 正如前面所指出的,dynamic_cast并不是免费提供的。处理大多数(但不是所有情况)的简单且一致的hack基本上是添加一个表示类可以拥有的所有可能类型的枚举,并检查您是否得到了正确的类型C++;相当于java';s实例 < C++ >代码> > > p> >使用: if(NewType* v = dynamic_cast<NewType*>(old)) { // old was safely casted to NewType v->doSomething(); } if(NewType*v=dynamic_cast(旧)){ //旧的铸成了新的 v->doSomething(); },java,c++,oop,instanceof,Java,C++,Oop,Instanceof,这要求编译器启用rtti支持 编辑: 我对这个答案有一些好的评论 每次你需要使用动态投射(或instanceof)时,你最好问问自己这是否是必要的。这通常是设计拙劣的标志 典型的解决方法是将您要检查的类的特殊行为放入基类上的虚拟函数中,或者可能引入类似的方法,在这种方法中,您可以在不更改接口的情况下为子类引入特定行为(当然,除了添加访问者接受接口) 正如前面所指出的,dynamic_cast并不是免费提供的。处理大多数(但不是所有情况)的简单且一致的hack基本上是添加一个表示类可以拥有的所有可
if(old->getType() == BOX) {
Box* box = static_cast<Box*>(old);
// Do something box specific
}
if(old->getType()==BOX){
盒子*盒子=静态_铸造(旧);
//做一些特定于盒子的事情
}
这不是一个好的oo设计,但它可以是一个解决方法,其成本或多或少只是一个虚拟函数调用。无论RTTI是否启用,它都可以工作
请注意,此方法不支持多级继承,因此如果不小心,可能会以如下代码结束:
// Here we have a SpecialBox class that inherits Box, since it has its own type
// we must check for both BOX or SPECIAL_BOX
if(old->getType() == BOX || old->getType() == SPECIAL_BOX) {
Box* box = static_cast<Box*>(old);
// Do something box specific
}
if (dynamic_cast<B*>(aPtr) != nullptr) {
// aPtr is instance of B
} else {
// aPtr is NOT instance of B
}
//这里有一个继承Box的SpecialBox类,因为它有自己的类型
//我们必须同时检查复选框或特殊复选框
if(old->getType()==BOX | | old->getType()==SPECIAL|BOX){
盒子*盒子=静态_铸造(旧);
//做一些特定于盒子的事情
}
#包括
#包括
模板
虚无乐趣(T a)
{
if(typeid(T)=typeid(int))
{
//做点什么
cout根据您想做的事情,您可以这样做:
template<typename Base, typename T>
inline bool instanceof(const T*) {
return std::is_base_of<Base, T>::value;
}
模板
内联布尔实例(常数T*){
return std::是::value的_base_;
}
使用:
if(instanceof(ptr)){…}
但是,这纯粹是对编译器已知的类型进行操作
编辑:
a2aPtr->instanceOf<A>(): expected=1, value=1
a2aPtr->instanceOf<B>(): expected=0, value=0
a2aPtr->instanceOf<C>(): expected=0, value=0
a2aPtr->instanceOf<D>(): expected=0, value=0
a2bPtr->instanceOf<A>(): expected=1, value=1
a2bPtr->instanceOf<B>(): expected=1, value=1
a2bPtr->instanceOf<C>(): expected=0, value=0
a2bPtr->instanceOf<D>(): expected=0, value=0
a2cPtr->instanceOf<A>(): expected=1, value=1
a2cPtr->instanceOf<B>(): expected=0, value=0
a2cPtr->instanceOf<C>(): expected=1, value=1
a2cPtr->instanceOf<D>(): expected=0, value=0
c2dPtr->instanceOf<A>(): expected=1, value=1
c2dPtr->instanceOf<B>(): expected=0, value=0
c2dPtr->instanceOf<C>(): expected=1, value=1
c2dPtr->instanceOf<D>(): expected=1, value=1
a2dPtr->instanceOf<A>(): expected=1, value=1
a2dPtr->instanceOf<B>(): expected=0, value=0
a2dPtr->instanceOf<C>(): expected=1, value=1
a2dPtr->instanceOf<D>(): expected=1, value=1
InstanceOf performance(A->D) : 390768 us
InstanceOf performance(A->C) : 333994 us
InstanceOf performance(A->B) : 334596 us
InstanceOf performance(A->A) : 300959 us
DynamicCast performance(A->D) : 331942 us
DynamicCast performance(A->C) : 303715 us
DynamicCast performance(A->B) : 400262 us
DynamicCast performance(A->A) : 324942 us
InstanceOf performance(A->D) : 209501 us
InstanceOf performance(A->C) : 208727 us
InstanceOf performance(A->B) : 207815 us
InstanceOf performance(A->A) : 197953 us
DynamicCast performance(A->D) : 259417 us
DynamicCast performance(A->C) : 256203 us
DynamicCast performance(A->B) : 261202 us
DynamicCast performance(A->A) : 193535 us
此代码适用于多态指针:
template<typename Base, typename T>
inline bool instanceof(const T *ptr) {
return dynamic_cast<const Base*>(ptr) != nullptr;
}
模板
内联布尔实例(常数T*ptr){
返回动态_cast(ptr)!=nullptr;
}
示例:动态强制转换
效率低下。它向上遍历继承层次结构,如果您有多个继承级别,并且需要检查对象是否是其类型层次结构中任何一个类型的实例,则这是唯一的解决方案
但是,如果仅检查对象是否正是您指定的类型的更有限形式的instanceof
,能够满足您的需要,那么下面的函数将更加高效:
template<typename T, typename K>
inline bool isType(const K &k) {
return typeid(T).hash_code() == typeid(k).hash_code();
}
模板
内联布尔isType(常数K&K){
返回typeid(T).hash_code()==typeid(k).hash_code();
}
下面是如何调用上述函数的示例:
DerivedA k;
Base *p = &k;
cout << boolalpha << isType<DerivedA>(*p) << endl; // true
cout << boolalpha << isType<DerivedB>(*p) << endl; // false
derivedak;
基准*p=&k;
无法在没有动态强制转换的情况下执行实例
我认为这个问题在今天仍然是相关的。使用C++11标准,您现在可以实现instanceof
函数,而不必像这样使用dynamic\u cast
:
// Here we have a SpecialBox class that inherits Box, since it has its own type
// we must check for both BOX or SPECIAL_BOX
if(old->getType() == BOX || old->getType() == SPECIAL_BOX) {
Box* box = static_cast<Box*>(old);
// Do something box specific
}
if (dynamic_cast<B*>(aPtr) != nullptr) {
// aPtr is instance of B
} else {
// aPtr is NOT instance of B
}
演示
然后,您可以按如下方式使用这些内容(,请谨慎使用):
DemoClassHierarchy.hpp*
#include "InstanceOfMacros.h"
struct A {
virtual ~A() {}
INSTANCE_OF_BASE_DECL(A)
};
INSTANCE_OF_IMPL(A)
struct B : public A {
virtual ~B() {}
INSTANCE_OF_SUB_DECL(B, A)
};
INSTANCE_OF_IMPL(B)
struct C : public A {
virtual ~C() {}
INSTANCE_OF_SUB_DECL(C, A)
};
INSTANCE_OF_IMPL(C)
struct D : public C {
virtual ~D() {}
INSTANCE_OF_SUB_DECL(D, C)
};
INSTANCE_OF_IMPL(D)
下面的代码提供了一个小演示,用于验证基本的正确行为
InstanceOfDemo.cpp
#include <iostream>
#include <memory>
#include "DemoClassHierarchy.hpp"
int main() {
A *a2aPtr = new A;
A *a2bPtr = new B;
std::shared_ptr<A> a2cPtr(new C);
C *c2dPtr = new D;
std::unique_ptr<A> a2dPtr(new D);
std::cout << "a2aPtr->instanceOf<A>(): expected=1, value=" << a2aPtr->instanceOf<A>() << std::endl;
std::cout << "a2aPtr->instanceOf<B>(): expected=0, value=" << a2aPtr->instanceOf<B>() << std::endl;
std::cout << "a2aPtr->instanceOf<C>(): expected=0, value=" << a2aPtr->instanceOf<C>() << std::endl;
std::cout << "a2aPtr->instanceOf<D>(): expected=0, value=" << a2aPtr->instanceOf<D>() << std::endl;
std::cout << std::endl;
std::cout << "a2bPtr->instanceOf<A>(): expected=1, value=" << a2bPtr->instanceOf<A>() << std::endl;
std::cout << "a2bPtr->instanceOf<B>(): expected=1, value=" << a2bPtr->instanceOf<B>() << std::endl;
std::cout << "a2bPtr->instanceOf<C>(): expected=0, value=" << a2bPtr->instanceOf<C>() << std::endl;
std::cout << "a2bPtr->instanceOf<D>(): expected=0, value=" << a2bPtr->instanceOf<D>() << std::endl;
std::cout << std::endl;
std::cout << "a2cPtr->instanceOf<A>(): expected=1, value=" << a2cPtr->instanceOf<A>() << std::endl;
std::cout << "a2cPtr->instanceOf<B>(): expected=0, value=" << a2cPtr->instanceOf<B>() << std::endl;
std::cout << "a2cPtr->instanceOf<C>(): expected=1, value=" << a2cPtr->instanceOf<C>() << std::endl;
std::cout << "a2cPtr->instanceOf<D>(): expected=0, value=" << a2cPtr->instanceOf<D>() << std::endl;
std::cout << std::endl;
std::cout << "c2dPtr->instanceOf<A>(): expected=1, value=" << c2dPtr->instanceOf<A>() << std::endl;
std::cout << "c2dPtr->instanceOf<B>(): expected=0, value=" << c2dPtr->instanceOf<B>() << std::endl;
std::cout << "c2dPtr->instanceOf<C>(): expected=1, value=" << c2dPtr->instanceOf<C>() << std::endl;
std::cout << "c2dPtr->instanceOf<D>(): expected=1, value=" << c2dPtr->instanceOf<D>() << std::endl;
std::cout << std::endl;
std::cout << "a2dPtr->instanceOf<A>(): expected=1, value=" << a2dPtr->instanceOf<A>() << std::endl;
std::cout << "a2dPtr->instanceOf<B>(): expected=0, value=" << a2dPtr->instanceOf<B>() << std::endl;
std::cout << "a2dPtr->instanceOf<C>(): expected=1, value=" << a2dPtr->instanceOf<C>() << std::endl;
std::cout << "a2dPtr->instanceOf<D>(): expected=1, value=" << a2dPtr->instanceOf<D>() << std::endl;
delete a2aPtr;
delete a2bPtr;
delete c2dPtr;
return 0;
}
#include <chrono>
#include <iostream>
#include <string>
#include "DemoClassHierarchy.hpp"
template <typename Base, typename Derived, typename Duration>
Duration instanceOfMeasurement(unsigned _loopCycles) {
auto start = std::chrono::high_resolution_clock::now();
volatile bool isInstanceOf = false;
for (unsigned i = 0; i < _loopCycles; ++i) {
Base *ptr = new Derived;
isInstanceOf = ptr->template instanceOf<Derived>();
delete ptr;
}
auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<Duration>(end - start);
}
template <typename Base, typename Derived, typename Duration>
Duration dynamicCastMeasurement(unsigned _loopCycles) {
auto start = std::chrono::high_resolution_clock::now();
volatile bool isInstanceOf = false;
for (unsigned i = 0; i < _loopCycles; ++i) {
Base *ptr = new Derived;
isInstanceOf = dynamic_cast<Derived *>(ptr) != nullptr;
delete ptr;
}
auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<Duration>(end - start);
}
int main() {
unsigned testCycles = 10000000;
std::string unit = " us";
using DType = std::chrono::microseconds;
std::cout << "InstanceOf performance(A->D) : " << instanceOfMeasurement<A, D, DType>(testCycles).count() << unit
<< std::endl;
std::cout << "InstanceOf performance(A->C) : " << instanceOfMeasurement<A, C, DType>(testCycles).count() << unit
<< std::endl;
std::cout << "InstanceOf performance(A->B) : " << instanceOfMeasurement<A, B, DType>(testCycles).count() << unit
<< std::endl;
std::cout << "InstanceOf performance(A->A) : " << instanceOfMeasurement<A, A, DType>(testCycles).count() << unit
<< "\n"
<< std::endl;
std::cout << "DynamicCast performance(A->D) : " << dynamicCastMeasurement<A, D, DType>(testCycles).count() << unit
<< std::endl;
std::cout << "DynamicCast performance(A->C) : " << dynamicCastMeasurement<A, C, DType>(testCycles).count() << unit
<< std::endl;
std::cout << "DynamicCast performance(A->B) : " << dynamicCastMeasurement<A, B, DType>(testCycles).count() << unit
<< std::endl;
std::cout << "DynamicCast performance(A->A) : " << dynamicCastMeasurement<A, A, DType>(testCycles).count() << unit
<< "\n"
<< std::endl;
return 0;
}
结果各不相同,基本上取决于编译器的优化程度。使用g++-std=c++11-O0-o instanceof performance instanceof performance InstanceOfPerformance编译性能度量程序。cpp
我的本地计算机上的输出为:
InstanceOf performance(A->D) : 699638 us
InstanceOf performance(A->C) : 642157 us
InstanceOf performance(A->B) : 671399 us
InstanceOf performance(A->A) : 626193 us
DynamicCast performance(A->D) : 754937 us
DynamicCast performance(A->C) : 706766 us
DynamicCast performance(A->B) : 751353 us
DynamicCast performance(A->A) : 676853 us
嗯,这个结果是非常严肃的,因为计时表明新方法与动态\u cast
方法相比并没有快多少。对于测试a
的指针是否是a
的实例的特殊测试用例来说,它的效率甚至更低,但是通过调整二进制代码来改变潮流使用编译器otpimization。相应的编译器命令是g++-std=c++11-O3-o instanceof performance instanceof performance InstanceOfPerformance.cpp
。在我的本地计算机上的结果令人惊讶:
InstanceOf performance(A->D) : 3035 us
InstanceOf performance(A->C) : 5030 us
InstanceOf performance(A->B) : 5250 us
InstanceOf performance(A->A) : 3021 us
DynamicCast performance(A->D) : 666903 us
DynamicCast performance(A->C) : 698567 us
DynamicCast performance(A->B) : 727368 us
DynamicCast performance(A->A) : 3098 us
如果您不依赖多重继承,不反对好的旧C宏、RTTI和模板元编程,也不懒得向类层次结构的类中添加一些小指令,那么这种方法可以稍微提高应用程序的性能,如果您经常检查inst指针的正确性。但请谨慎使用。不保证此方法的正确性
注:所有演示均使用macOS Sierra下的clang(Apple LLVM 9.0.0版(clang-900.0.39.2))
在MacBook Pro 2012年年中编译
编辑:
我还使用gcc(Ubuntu 5.4.0-6ubuntu1~16.04.9)5.4.0 20160609
在Linux机器上测试了性能。在这个平台上,性能优势不如在使用clang的macOs上显著
输出(无编译器优化):
a2aPtr->instanceOf<A>(): expected=1, value=1
a2aPtr->instanceOf<B>(): expected=0, value=0
a2aPtr->instanceOf<C>(): expected=0, value=0
a2aPtr->instanceOf<D>(): expected=0, value=0
a2bPtr->instanceOf<A>(): expected=1, value=1
a2bPtr->instanceOf<B>(): expected=1, value=1
a2bPtr->instanceOf<C>(): expected=0, value=0
a2bPtr->instanceOf<D>(): expected=0, value=0
a2cPtr->instanceOf<A>(): expected=1, value=1
a2cPtr->instanceOf<B>(): expected=0, value=0
a2cPtr->instanceOf<C>(): expected=1, value=1
a2cPtr->instanceOf<D>(): expected=0, value=0
c2dPtr->instanceOf<A>(): expected=1, value=1
c2dPtr->instanceOf<B>(): expected=0, value=0
c2dPtr->instanceOf<C>(): expected=1, value=1
c2dPtr->instanceOf<D>(): expected=1, value=1
a2dPtr->instanceOf<A>(): expected=1, value=1
a2dPtr->instanceOf<B>(): expected=0, value=0
a2dPtr->instanceOf<C>(): expected=1, value=1
a2dPtr->instanceOf<D>(): expected=1, value=1
InstanceOf performance(A->D) : 390768 us
InstanceOf performance(A->C) : 333994 us
InstanceOf performance(A->B) : 334596 us
InstanceOf performance(A->A) : 300959 us
DynamicCast performance(A->D) : 331942 us
DynamicCast performance(A->C) : 303715 us
DynamicCast performance(A->B) : 400262 us
DynamicCast performance(A->A) : 324942 us
InstanceOf performance(A->D) : 209501 us
InstanceOf performance(A->C) : 208727 us
InstanceOf performance(A->B) : 207815 us
InstanceOf performance(A->A) : 197953 us
DynamicCast performance(A->D) : 259417 us
DynamicCast performance(A->C) : 256203 us
DynamicCast performance(A->B) : 261202 us
DynamicCast performance(A->A) : 193535 us
输出(带编译器优化):
a2aPtr->instanceOf<A>(): expected=1, value=1
a2aPtr->instanceOf<B>(): expected=0, value=0
a2aPtr->instanceOf<C>(): expected=0, value=0
a2aPtr->instanceOf<D>(): expected=0, value=0
a2bPtr->instanceOf<A>(): expected=1, value=1
a2bPtr->instanceOf<B>(): expected=1, value=1
a2bPtr->instanceOf<C>(): expected=0, value=0
a2bPtr->instanceOf<D>(): expected=0, value=0
a2cPtr->instanceOf<A>(): expected=1, value=1
a2cPtr->instanceOf<B>(): expected=0, value=0
a2cPtr->instanceOf<C>(): expected=1, value=1
a2cPtr->instanceOf<D>(): expected=0, value=0
c2dPtr->instanceOf<A>(): expected=1, value=1
c2dPtr->instanceOf<B>(): expected=0, value=0
c2dPtr->instanceOf<C>(): expected=1, value=1
c2dPtr->instanceOf<D>(): expected=1, value=1
a2dPtr->instanceOf<A>(): expected=1, value=1
a2dPtr->instanceOf<B>(): expected=0, value=0
a2dPtr->instanceOf<C>(): expected=1, value=1
a2dPtr->instanceOf<D>(): expected=1, value=1
InstanceOf performance(A->D) : 390768 us
InstanceOf performance(A->C) : 333994 us
InstanceOf performance(A->B) : 334596 us
InstanceOf performance(A->A) : 300959 us
DynamicCast performance(A->D) : 331942 us
DynamicCast performance(A->C) : 303715 us
DynamicCast performance(A->B) : 400262 us
DynamicCast performance(A->A) : 324942 us
InstanceOf performance(A->D) : 209501 us
InstanceOf performance(A->C) : 208727 us
InstanceOf performance(A->B) : 207815 us
InstanceOf performance(A->A) : 197953 us
DynamicCast performance(A->D) : 259417 us
DynamicCast performance(A->C) : 256203 us
DynamicCast performance(A->B) : 261202 us
DynamicCast performance(A->A) : 193535 us
性能和兼容性比较好……问“Staskof——用什么语言?”MyTurbo是不公平的吗?MyTurbo:我得到了“保加利亚”,GT不支持C++。检查是否必须使用instanceof,在大多数情况下,您的设计都有问题。别忘了dynamic_cast是一个成本高昂的操作。有很多合理使用动态类型测试的例子。通常不喜欢使用instanceof,但它有一席之地。(否则,为什么它或它的等价物