gpt4 book ai didi

c++ - "inherit"另一个关系 (1 :N) relationship

转载 作者:行者123 更新时间:2023-11-30 03:22:26 25 4
gpt4 key购买 nike

我想要一个支持这些特定 1:N 关系的数据结构:-
1#。 人类 raise 0-N 人类
2#。 0-N
3#。 人类 培养 0-N
4#。 是一所 0-N 寄生虫

enter image description here

注意:
- 这些关系中的状态都是暂时的,例如Human1 可能培养 Human2,但一年后,Human1 可能会放弃 Human2
- 所有对象都继承自 BaseObject 并具有唯一的 int ID。

在上述所有关系中,我希望能够支持这些功能:-
F1。添加关系,例如human_dog->addRelation(Human* a,Dog* b)
F2。删除关系,例如human_dog->removeRelation(Human* a,Dog* b)
F3。查询所有 child ,例如human_dog->getAllChildren(Human*)
F4。查询所有父级,例如human_dog->getAllParents(Dog*)
F5。检查 parent 是否有 >=1 个 child
F6。检查一个 child 是否有 >=1 个 parent
F7。删除父项的所有子项
F8。删除 child 的所有 parent

这可以通过 std::unordered_map 或更容易定制的东西来实现。

困难的部分来了

我想将关系 1#、2#、3#(即所有实线)标记为 Feed
它必须以聚合 风格支持功能 F3-F8。

例如:-

  • feed->getAllChildren(BaseObject* b) :
    如果 b 是人类,它必须返回 raisehascultivate 的所有 child b
  • feed->removeAllParent(BaseObject* b) :
    如果b是一只狗,它的效果类似于cultivate->removeAllParent(b)

总而言之,我希望能够轻松地注入(inject)这样的聚合
前任。调用 :-

很有用
void BaseObject::declareForFreedom(){
feed->removeAllParent(this);
}

上面的例子只显示了 4 个关系和 1 个间接级别。
在我的真实案例中,有 8-10 个关系和 3-4 个级别的这种继承/间接。

问题

适合这种情况的数据结构/设计模式是什么?

我目前为 1#-4# 创建自定义 1:N 关系,并对每个 feed 的功能进行硬编码。这很乏味。
我已经摸索了几个月,但没有找到任何看起来优雅的实现。

演示

http://coliru.stacked-crooked.com/a/1f2decd7a8d96e3c

基本类型:-

#include <iostream>
#include <map>
#include <vector>
enum class Type{
HUMAN,DOG,TREE,PARASITE,ERROR
}; //for simplicity
class BaseObject{public: Type type=Type::ERROR; };
class Human : public BaseObject{
public: Human(){ type=Type::HUMAN; }
};
class Dog : public BaseObject{
public: Dog(){ type=Type::DOG; }
};
class Tree : public BaseObject{
public: Tree(){ type=Type::TREE; }
};
class Parasite : public BaseObject{
public: Parasite(){ type=Type::PARASITE; }
};

基本1:N map

template<class A,class B> class MapSimple{
std::multimap<A*, B*> aToB;
std::multimap<B*, A*> bToA;
public: void addRelation(A* b1,B* b2){
aToB.insert ( std::pair<A*,B*>(b1,b2) );
bToA.insert ( std::pair<B*,A*>(b2,b1) );
}
public: std::vector<B*> queryAllChildren(A* b1){
auto ret = aToB.equal_range(b1);
auto result=std::vector<B*>();
for (auto it=ret.first; it!=ret.second; ++it){
result.push_back(it->second);
}
return result;
}
public: void removeAllParent(B* b){
if(bToA.count(b)==0)return;
A* a=bToA.find(b)->second;
bToA.erase(b);
auto iterpair = aToB.equal_range(a);
auto it = iterpair.first;
for (; it != iterpair.second; ++it) {
if (it->second == b) {
aToB.erase(it);
break;
}
}
}
//.. other functions
};

这是数据库实例和聚合:-

MapSimple<Human,Human> raise;
MapSimple<Human,Dog> has;
MapSimple<Human,Tree> cultivate;
MapSimple<Dog,Parasite> isHouseOf;
class Feed{
public: void removeAllParent(BaseObject* b1){
if(b1->type==Type::HUMAN){
raise.removeAllParent(static_cast<Human*>(b1));
}
if(b1->type==Type::DOG){
has.removeAllParent(static_cast<Dog*>(b1));
}
//.... some other condition (I have to hard code them - tedious) ...
}
//other function
};
Feed feed;

用法

int main(){
Human h1;
Dog d1,d2;

has.addRelation(&h1,&d1);
has.addRelation(&h1,&d2);
auto result=has.queryAllChildren(&h1);
std::cout<<result.size(); //print 2
feed.removeAllParent(&d1);
result=has.queryAllChildren(&h1);
std::cout<<result.size(); //print 1
}

最佳答案

直接实现有什么问题?

例如:基础对象.hpp

#include <vector>

template<class T>
using prtVector = std::vector<T*>;

class BaseObject {
public:
virtual prtVector<BaseObject> getAllParents() const = 0;
virtual prtVector<BaseObject> getAllChilderen() const = 0;
virtual void removeAllParents() = 0;
virtual void removeAllChildren() = 0;
};

人类.hpp

#include "BaseObject.hpp"
#include "Tree.hpp"
#include "Dog.hpp"
class Tree;
class Dog;

class Human : public BaseObject {
public:
prtVector<BaseObject> getAllParents() const override;
prtVector<BaseObject> getAllChildren() const override;

void removeAllParents() override;
void removeAllChildren() override ;

friend class Dog;
friend class Tree;
template<class A, class B>
friend void addRelation(A* a, B* b);
private:
void addParent(Human* const);
void removeParent(Human const* const);
void addChild(Human* const);
void removeChild(Human const* const);
void addChild(Tree* const);
void removeChild(Tree const* const);
void addChild(Dog* const);
void removeChild(Dog const* const);
private:
prtVector<Human> parents;
prtVector<Human> children;
prtVector<Tree> plants;
prtVector<Dog> pets;
};

人类.cpp

#include "Human.hpp"

prtVector<BaseObject> Human::getAllParents() const {
prtVector<BaseObject> result(std::cbegin(parents), std::cend(parents));
return result;
}

prtVector<BaseObject> Human::getAllChildren() const {
prtVector<BaseObject> result(std::cbegin(children), std::cend(children));
result.insert(std::end(result), std::cbegin(pets), std::cend(pets));
result.insert(std::end(result), std::cbegin(plants), std::cend(plants));
return result;
}

void Human::removeAllParents() {
for (auto parent : parents) { parent->removeChild(this); }
parents.clear();
}

void Human::removeAllChildren() {
for (auto child : children) { child->removeParent(this); } children.clear();
for (auto pet : pets) { pet->removeParent(this); } pets.clear();
for (auto plant : plants) { plant->removeParent(this); } plants.clear();
}

void Human::addParent(Human* const parent) { parents.push_back(parent); }

#include <algorithm>
void Human::removeParent(Human const* const parent) {
auto it = std::find(std::cbegin(parents), std::cend(parents), parent);
if (it != std::cend(parents)) parents.erase(it);
}
void Human::addChild(Human* const child) { children.push_back(child); }

等等等等......

其他类型也一样....

主要.cpp

#include "Human.hpp"
#include "Dog.hpp"

template<class A, class B>
void addRelation(A* a, B* b)
{
a->addChild(b);
b->addParent(a);
}

template<class A>
prtVector<BaseObject> queryAllChildren(A* obj)
{
return obj->getAllChilderen();
}

template<class A>
void removeAllParents(A* obj)
{
obj->removeAllParents();
}

#include <iostream>
int main() {
Human h1;
Dog d1, d2;

addRelation(&h1, &d1);
addRelation(&h1, &d2);
auto result = queryAllChildren(&h1);
std::cout << result.size() << "\n"; //print 2
removeAllParents(&d1);
result = queryAllChildren(&h1);
std::cout << result.size() << "\n"; //print 1

std::cin.ignore();
}

恕我直言,这提供了可读和可维护的代码。可能可以进行一些优化。但至少代码中的关系非常清楚。

关于c++ - "inherit"另一个关系 (1 :N) relationship,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51149076/

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