假设我有一个基础抽象类B
和一百个派生自D1
... D100
的类。我还有两个(智能)指针unique_ptr<B> p1, p2;
,指向两个不同的类型Di
和Dj
的实例。我想知道他们指向的对象是否具有相同的类型(即i
是否等于j
)。有一个简单的方法吗?
答案 0 :(得分:7)
您可以使用RTTI typeid,但通常情况下,必须使用dynamic_cast是一个糟糕的设计,因为它可能违反了liskov替换原则
std::unique_ptr<B> p1, p2;
if(typeid(*p1) == typeid(*p2)) // correction by Justin
使用name
或hash_code
答案 1 :(得分:5)
检查C ++ RTTI相对昂贵且繁琐:考虑在基类中添加事件标记,并检查该值。
enum class EventTag {
A, B
};
struct EventBase {
const EventTag tag;
EventBase(EventTag tag) : tag(tag) {
}
};
struct EventA : public EventBase {
EventA() : EventBase(EventTag::A) {
}
};
struct EventB : public EventBase {
EventB() : EventBase(EventTag::B) {
}
};
if (thisEvent->tag == thatEvent->tag) {
// stuff
}
联盟而不是类层次结构也可以为你做。
答案 2 :(得分:0)
这可能看起来有点复杂,但它可以确保您在比较方面的可操作性。这种方法在可维护性方面有更多的开销,但它将确保正确的比较,而不会在时间执行方面执行过多的开销。
#include <string>
#include <iostream>
#include <memory>
class AbstractBase {
public:
enum DerivedTypes {
DERIVED_A,
DERIVED_B
};
protected:
DerivedTypes type_;
public:
explicit AbstractBase( const DerivedTypes type ) : type_( type ) {}
virtual void print() = 0;
DerivedTypes getType() const {
return type_;
}
bool operator==( const AbstractBase& other ) {
return this->type_ == other.getType();
}
};
class DerivedA : public AbstractBase {
public:
const int x = 5;
public:
explicit DerivedA( const DerivedTypes type = DerivedTypes::DERIVED_A ) : AbstractBase( type ) {}
virtual void print() override {
std::cout << "DerivedA\n";
}
};
class DerivedB : public AbstractBase {
public:
const float y = 1.5f;
public:
explicit DerivedB( const DerivedTypes type = DerivedTypes::DERIVED_B ) : AbstractBase( type ) {}
virtual void print() override {
std::cout << "DerivedB\n";
}
};
int main() {
std::unique_ptr<DerivedA> p1 = std::make_unique<DerivedA>( DerivedA() );
std::unique_ptr<DerivedB> p2 = std::make_unique<DerivedB>( DerivedB() );
p1->print();
p2->print();
if ( *p1 == *p2 ) {
std::cout << "pointers are the same\n";
} else {
std::cout << "pointers are not the same\n";
}
std::unique_ptr<DerivedA> p3 = std::make_unique<DerivedA>( DerivedA() );
std::unique_ptr<DerivedA> p4 = std::make_unique<DerivedA>( DerivedA() );
p3->print();
p4->print();
if ( *p3 == *p4 ) {
std::cout << "pointers are the same\n";
} else {
std::cout << "pointers are not the same\n";
}
return 0;
}
此处可维护性的增加成本取决于有多少派生类。如果从一开始就使用这种设计模式,那么很容易遵循。如果必须修改可计算数量的类,则需要花费一些时间和精力来修改现有的代码库。
这里的想法是抽象基类保留派生类型的内部变量,具有它的派生类型&amp;一个比较类型的重载==比较运算符。构造函数被强制采用其枚举类型以及所有派生类型。我还默认了派生类型,因此每次实例化类对象时都不必将它传递给它们的构造函数。这是可维护性的开销。
比较指针 - 多个派生类型的智能指针时,这种简单性就会发挥作用。当您查看上面的主函数时,您可以看到它非常简单,可以取消引用智能指针,基类的重载==运算符可以处理业务。
如果确实需要使用operator==()
来实际比较类之间的数值差异,那么可以修改它以在基类中使用公共方法来比较类型并返回bool而不是重载运算符。