通过隐式类型转换模拟接口
Simulating an interface by implicit typecast
假设我有几个类A1
, A2
, A3
,它们的数据可以存储在同一个POD数据结构D
中。这些类在如何管理数据方面有所不同,例如,在何处分配动态数据结构。然而在语义上,它们表示所有相同类型的数据。
我的A?
类之一被设计为D
的包装器,它可以基于现有的D
而不复制它。
现在我想以统一的方式实现所有A?
类的读访问。我不想使用虚方法,也不想模板化所有使用A?
类的代码。
下面的设计合理吗?
这个模式有名字吗?(Facade)
有明显的陷阱吗?
/* in practice, D is large or should not be copied for other reasons */
struct D { int * mymember; }
struct ACRef {
ACRef (D const & d) : m_dataref (&d) { }
/* operations for A-like classes */
int getMyMember () const { return *(m_dataref->mymember); }
private:
D const * m_dataref;
};
struct A1 {
/* A1 stuff, manages m_data.mymember in a particular way */
// implicit conversion to ACRef possible
// kind of "is a" relationship: an A1 "is an" ACRef
operator ACRef () { return ACRef {this->m_data}; }
private:
D m_data;
};
struct A2 {
explicit A2 (D & d) : m_data (&d) { }
/* A2 stuff, manages m_data.mymember in a particular way */
// implicit conversion to ACRef possible
// kind of "is a" relationship: an A2 "is an" ACRef
operator ACRef () { return ACRef {*(this->m_data)}; }
private:
D * m_data;
};
/* A3 defined similar to A1 */
/* function that should operate on A?'s */
int printMyMember (ACRef a) {
std::cout << a.getMyMember () << std::endl;
}
A1 a1;
A2 a2;
// ...
printMyMember (a1);
printMyMember (a2);
我认为这种方法的唯一缺点是最终会有多个隐式共享状态的对象。因此,例如通过值传递ACRef并不具有典型的含义。但是只要你只允许通过ACRef
读访问,这应该不是一个大问题。
如果代理类型最终出现在与原始对象不同的线程中,那么您必须非常小心。
我看不出你的方法有什么明显的错误,但明智的人告诉我要避免隐式类型转换,所以这让我有点紧张。每次利用"is-a"关系时,都有创建新对象的味道。
表示"is-a"关系的更惯用的方法是使用继承。
为了满足您对ACRef
的需求,我们可以使用Base-from-Member习语:
struct D { int member; };
class ACRef {
const D *data_ref;
public:
ACRef(const D &data) : data_ref(&data){}
int getMember() const { return data_ref->member; }
};
struct BaseA {
D data;
BaseA() : data({0}){}
};
class A1 : protected BaseA, public ACRef {
public:
A1() : ACRef(data){}
};
class A2 : protected BaseA, public ACRef {
public:
A2() : ACRef(data){}
};
void printMyMember(const ACRef& a) {
std::cout << a.getMember() << "n";
}
int main() {
A1 a1;
printMyMember(a1);
D d = {1};
ACRef acref(d);
printMyMember(d);
}
我不认为你可以依赖offsetof(m_data)是一致的(你的例子混合了完整成员和指针)
为了得到保证的行为,你需要一个基类来定义通用的行为。
class Abase{ protected D* m_data;...}
只有这样,对于某些A
相关文章:
- 如何使用Google Mock来模拟gettimeofday()
- G锁定铸造到基础上会释放模拟行为
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- Visual C++GC接口如何启用它以及要包含哪个库
- 落砂模拟碰撞检测C++和SFML
- Windows.h与GLFW.h的接口
- 在gtest.中使用fff.h模拟系统API
- 谷歌模拟和覆盖关键字
- 用C#中的并集模拟C++嵌套结构
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 提供与TMP和SFINAE的通用接口
- 为重写std::exception的库生成swig接口时出错
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 内联如何影响模块接口中的成员函数
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 除了模拟测试之外,还无需额外使用接口
- 通过隐式类型转换模拟接口
- 在c++中模拟一个COM接口