gpt4 book ai didi

c++ - 处理多态对象集合的正确设计模式

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:59:21 24 4
gpt4 key购买 nike

假设我有以下类:

class BaseObject {
public:
virtual int getSomeCommonProperty();
};

class Object1: public BaseObject {
public:
virtual int getSomeCommonProperty(); // optional
int getSomeSpecificProperty();
};

class BaseCollection {
public:
virtual void someCommonTask();
};

class Collection1: public BaseCollection {
public:
virtual void someCommonTask(); // optional
void someSpecificTask();
};

从 BaseCollection 派生的每个集合都处理特定的对象类型(并且只有一种类型)。但是 BaseCollection 应该能够执行一些所有对象共有的任务,只使用 BaseObject 中的公共(public)对象属性。

目前,我想到了三种可能的解决方案:

1)将对象列表存储在BaseCollection中,如:

class BaseCollection {
vector<BaseObject*> objects;
};

这个解决方案的问题是,当我需要在Collection1中执行特定于对象的任务时,我需要一个dynamic_cast<>,因为我不想对特定属性使用虚拟继承,只应用于一种类型的对象.考虑到 dynamic_cast<> 可能每秒被调用数百万次,这对于性能关键型应用程序来说似乎是一个问题。

2)将对象列表存储在Collection1中,如:

class Collection1: public BaseCollection {
vector<Object1*> objects;
}

但是我需要一些方法来访问 BaseCollection 中的这个对象列表,以便能够对它们执行一些常见的任务,最好是通过迭代器。我需要创建一个函数来为 BaseCollection 返回一个 vector ,但同样,这似乎不是很有效,因为这样做的唯一方法是创建一个新 vector (可能包含数千个对象)...

3) 将对象列表存储在 BaseCollection AND Collection1 中:

class BaseCollection {
public:
void someCommonTask(); // Use baseObjects
virtual void addObject() = 0;

protected:
vector<BaseObject*> baseObjects;
};

class Collection1: public BaseCollection {
vector<Object1*> objects;

public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}

void someSpecificTask(); // Use objects, no need of dynamic_cast<>
}

两个列表实际上包含相同的对象。这听起来很丑陋吗?

我正在为这类问题寻找正确/正确/最佳的设计模式,上面公开的 3 种解决方案都没有真正让我满意......

也许可以用模板解决这个问题,但是我没有看到像这样存储多态集合列表的方法:

vector<BaseCollection*> collections;

最佳答案

您可以通过基类(智能)指针将基类和派生类的所有对象存储在一个集合中。使用 visitor design patterndouble dispatch机制,您可以仅在特定类型的对象上调用函数,而不必在基类接口(interface)中公开该函数。例如:

#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <stdio.h>

struct Visitor { // Visitor design patter
virtual void visit(struct BaseObject&) {}
virtual void visit(struct Object1&) {}
};

struct BaseObject {
unsigned ref_count_; // intrusive_ptr support
BaseObject() : ref_count_() {}
virtual ~BaseObject() {}
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};

void intrusive_ptr_add_ref(BaseObject* p) { // intrusive_ptr support
++p->ref_count_;
}

void intrusive_ptr_release(BaseObject* p) { // intrusive_ptr support
if(!--p->ref_count_)
delete p;
}

struct Object1 : BaseObject {
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
void getSomeSpecificProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class T, class Functor>
struct FunctorVisitor : Visitor {
Functor f_;
FunctorVisitor(Functor f) : f_(f) {}
void visit(T& t) { f_(t); } // apply to T objects only
template<class P> void operator()(P const& p) { p->accept(*this); }
};

template<class T, class Functor>
FunctorVisitor<T, Functor> apply_to(Functor f)
{
return FunctorVisitor<T, Functor>(f);
}

int main()
{
typedef boost::intrusive_ptr<BaseObject> BaseObjectPtr;
typedef std::vector<BaseObjectPtr> Objects;

Objects objects;
objects.push_back(BaseObjectPtr(new BaseObject));
objects.push_back(BaseObjectPtr(new Object1));

for_each(
objects.begin()
, objects.end()
, boost::bind(&BaseObject::getSomeCommonProperty, _1)
);

for_each(
objects.begin()
, objects.end()
, apply_to<BaseObject>(boost::bind(&BaseObject::getSomeCommonProperty, _1))
);

for_each(
objects.begin()
, objects.end()
, apply_to<Object1>(boost::bind(&Object1::getSomeSpecificProperty, _1))
);
}

输出:

$ ./test
virtual void BaseObject::getSomeCommonProperty()
virtual void Object1::getSomeCommonProperty()
virtual void BaseObject::getSomeCommonProperty()
void Object1::getSomeSpecificProperty()

关于c++ - 处理多态对象集合的正确设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4773359/

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