如何解决基于类的类型的引用计数实例
| 考虑以下代码:struct I
{
SomeInternalState m_internalState;
};
struct S
{
I * m_i;
set_I (I * i)
{
m_i = i;
makeSomeChangesToTheInternalStateOfI(m_i);
}
};
struct S_1 : S { ... };
struct S_2 : S { ... };
...
struct S_n : S { ... };
假定可以创建任意数量的S_1
,...S_n
实例,并且它们全部将仅调用set_I()
一次。
现在,我希望每个类型S_x
的每个I
实例的S_1
,... ...2ѭ到makeSomeChangesToTheInternalStateOfI()
实例一次,这样我就可以从相同类S_x
的不同实例和相同的I
实例中调用set_I()
,并确保ѭ7'的内部状态仅在第一次通话时才被修改。
可能的决定是将一些分配表放入ѭ7中,但我认为它不是一个明智的键,仅基于S_x
实例的类型并且不涉及任何手写的“运行时类型id”常量所有可能的类型S_1
,...S_n
。
我该怎么做?
编辑:
我应该强调的几点:
1)一次可能会有一个以上的ѭ7instance实例,并且S_x
类应该能够更改I
的多个实例的状态,但每个实例只能更改一次。那是:
I i1,i2;
S_1 s1a,s1b;
S_2 s2a,s2b;
// all possible combinations:
s1a.changeStateOfI(i1);
s1b.changeStateOfI(i1);
s2a.changeStateOfI(i1);
s2b.changeStateOfI(i1);
s1a.changeStateOfI(i2);
s1b.changeStateOfI(i2);
s2a.changeStateOfI(i2);
s2b.changeStateOfI(i2);
在此片段中,ѭ21和22的状态仅应通过ѭ1方法(通过ѭ24)更改一次,并通过by25'(通过'26ѭ)更改一次。
2)我想,可以使用引用计数来解决问题-无需确切知道初始化发生了多少次,就足以知道是否进行了初始化。
编辑2
我将n.m.的建议标记为答案,尽管我的最终解决方案有所不同。在这里,以便其他人也可以使用它:
struct AbstractS
{
I * m_i;
virtual void set_I (I * i) = 0;
};
template <typename self_T>
struct RegS : AbstractS
{
static std::set<I *> s_registeredContexts;
virtual void set_I (I * i)
{
m_i = i;
if (i == NULL || s_registeredContexts.count(i) > 0) return;
makeSomeChangesToTheInternalStateOfI(i);
contexts.insert(i);
}
};
template <typename self_T>
std::set<I *> InterpreterState<self_T>::s_registeredContexts;
struct S_1 : RegS<S_1> { ... };
struct S_2 : RegS<S_2> { ... };
...
struct S_n : RegS<S_n> { ... };
与n.m.的变体相比,差异在于我在这里使用了CRTP模式,而不是枚举实例化,这也是我想避免的事情。
解决方法
您可以使用
typeinfo
作为键,但这不是一个好主意。您不应该在程序中计算类型。让我用一个简单的例子来解释。
假设您有一个Vehicle
类型及其后代Car
,Truck
和Bike
。您可以为每个这些类调用一次函数。到目前为止,一切都很好。现在,出于完全不相关的原因,您需要处理SUV,RacingCars,GarbageTruck,Trikes,RedCars,ReddishCars和YellowishReddishWithGreenishTintCars。您对函数将被调用的次数的决定应与针对每种情况引入或不引入单独的类的决定完全正交。
因此,您只需要为每堆相似对象调用一次函数的目的就可以将Vehicles标记为与众不同或相似。一种实现方法是使用类模板和一堆类型参数(任何类型的参数)。
class ChangerOfInternalStateOfI
{
public:
ChangerOfInternalStateOfI (I* i) {
makeSomeChangesToTheInternalStateOfI(i);
}
};
template <int n>
class S_N : public S
{
public:
S_N() {
static ChangerOfInternalStateOfI changer;
}
};
typedef S_N<1> S_1;
typedef S_N<2> S_2;
您可以使用enum代替int或类型名,这并不重要。关键是您所有的ChangerOfInternalStateOfI都是不同的,因为它们属于不同的类,并且每个构造函数都将被调用一次。
, 如果该方式具有静态数据成员n.m.提到的不符合目标,
在I
中处理过包含类型的集合怎么样?
由于ѭ35本身并不比同类产品差,因此一个简单的包装器
以下代码中使用36。
如果必须多态地进行类型检查(通过基本类S
),
需要运行时类型信息。
所以我使changeStateOfI
成为virtual
。
#include <typeinfo>
#include <set>
using namespace std;
struct type_info_ {
type_info const *t;
type_info_( type_info const* t ) : t( t ) {}
bool operator<( type_info_ const& x ) const { return t->before( *x.t ); }
};
struct I {
set< type_info_ > types;
void f( type_info const& t,char const* s ) {
if ( types.insert( type_info_( &t ) ).second ) { puts( s ); }
}
};
struct S {
virtual void changeStateOfI( I& i,char const* s ) {
i.f( typeid( *this ),s );
}
};
struct S_1 : S {};
struct S_2 : S {};
int main() {
I i1,i2;
S_1 s1a,s1b;
S_2 s2a,s2b;
s1a.changeStateOfI(i1,\"s1a i1\");
s1b.changeStateOfI(i1,\"s1b i1\");
s2a.changeStateOfI(i1,\"s2a i1\");
s2b.changeStateOfI(i1,\"s2b i1\");
s1a.changeStateOfI(i2,\"s1a i2\");
s1b.changeStateOfI(i2,\"s1b i2\");
s2a.changeStateOfI(i2,\"s2a i2\");
s2b.changeStateOfI(i2,\"s2b i2\");
}
上面的代码分别是s1a i1
,s2a i1
,s1a i2
,s2a i2
在我的环境中
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。