gpt4 book ai didi

c++ - 在 unordered_set 中存储多态对象

转载 作者:行者123 更新时间:2023-11-28 04:18:58 33 4
gpt4 key购买 nike

假设我有一个基类

struct Base {
int x;
};

我知道有一个 Derived派生自 Base 的类,但此时我无法获得它的定义(它存在于下游模块中)。

现在我有一个 unordered_set<Base*>它将存储 Base 的混合物和 Derived对象。如果我不指定自定义散列函数,这个 unordered_set 是否会正常工作(即按元素的实际类型散列元素,以便两个 Derived 具有相同 x 但在其他一些派生字段中不同的对象被视为不同)?

假设我确实需要自定义哈希函数,因为我没有 Derived 的定义然而,我希望将我的散列函数写成 Base 的虚拟成员函数。这样Derivedunordered_set 时,可以简单地覆盖该函数以执行其自己的哈希要求它。这可能吗?或者对于此类问题是否有其他首选/既定解决方案?

最佳答案

是的,你可以这样做:

#include <iostream>
#include <functional>
#include <unordered_set>
#include <memory>

struct Base {
int x;

virtual size_t hash() const {
return std::hash<int>()(x);
}
};

// just some Derived example
struct Derived : Base {
int y;

// performing hashing for a pair of integers
virtual size_t hash() const override {
return std::hash<int>()(x) ^ std::hash<int>()(y);
}
};

struct Hasher {
size_t operator()(const Base* ptr) const {
return ptr->hash();
}
};

struct CheckEq {
bool operator()(Base* lhs, Base* rhs) const {
auto dLhs = dynamic_cast<Derived*>(lhs);
auto dRhs = dynamic_cast<Derived*>(rhs);

// different types
if ((dLhs == nullptr) != (dRhs == nullptr)) {
return false;
}

// both Base
if (dLhs == nullptr && dRhs == nullptr) {
return lhs->x == rhs->x;
}

// both Derived
return dLhs->x == dRhs->x && dLhs->y == dRhs->y;
}
};

int main() {
std::unordered_set<
Base*,
Hasher, // struct with defined size_t operator()(const Base*) const, returning hash of object
CheckEq // struct with defined bool operator(const Base*, const Base*) const for additional checking whether 2 objects with same hashes are different
> set;

// checking if it works
auto objBase1 = std::make_unique<Base>();
objBase1->x = 5;
auto objBase2 = std::make_unique<Base>();
objBase2->x = 5;
auto objBase3 = std::make_unique<Base>();
objBase3->x = 6;

auto objDerived1 = std::make_unique<Derived>();
objDerived1->x = 5;
objDerived1->y = 6;
auto objDerived2 = std::make_unique<Derived>();
objDerived1->x = 5;
objDerived1->y = 6;
auto objDerived3 = std::make_unique<Derived>();
objDerived1->x = 50;
objDerived1->y = 60;

set.insert(objBase1.get());
set.insert(objBase2.get());
set.insert(objBase3.get());
set.insert(objDerived1.get());
set.insert(objDerived2.get());
set.insert(objDerived3.get());

std::cout << set.size() << std::endl; // prints 4

return 0;
}

UPD。在我看来你需要在某处存储对象,所以

std::unordered_set<
std::unique_ptr<Base>, // or shared_ptr
Hasher,
CheckEq
> set;

可能是个更好的主意。

关于c++ - 在 unordered_set 中存储多态对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55895037/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com