我是C++的新手,并且正在努力与二进制方法(例如,相等性)结合来理解数据抽象。我想定义一个接口(interface)
class A {
public:
static A* Make(int);
virtual ~A() {};
virtual bool Eq(A*) = 0;
};
使用工厂模式,我可以隐藏实现:
class B : public A {
public:
B(int x) : x_(x) {}
bool Eq(A* a) {
return x_ == dynamic_cast<B*>(a)->x_;
}
private:
int x_;
};
A* A::Make(int x) {
return new B(x);
}
然后,我可以使用抽象:
A* a = A::Make(1);
A* b = A::Make(2);
if (a->Eq(b)) {
cout << "Yes!" << endl;
} else {
cout << "No!" << endl;
}
但是,动态转换很糟糕,原因有很多。我看到的最大问题是,可以用C继承A的子类,然后将类型为C的对象传递给a-> Eq,这将导致未定义的行为。我无法弄清楚如何定义一个二进制方法,以使代码可以访问两个对象的私有(private)成员。我的直觉是,可以使用访问者模式来完成此操作,但是我无法提出解决方案。
对于那些了解ML的人,我基本上想做以下事情:
module A : sig
type t
val make: int -> t
val eq: t -> t -> bool
end = struct
type t = int
let make x = x
let eq x y = (x = y)
end
最佳答案
扩展我的评论,您可以使用PIMPL(实现的指针)惯用法编写代码,如下所示:
在您的头文件(a.hpp)中
class A
{
public:
A(int);
~A();
bool Eq(const A& a) const;
private:
class AImpl;
AImpl* implementation_;
};
在执行文件(a.cpp)中
struct A::AImpl {
AImpl(int x) : x_(x) {}
int x_;
};
A::A(int x)
: implementation_(new AImpl(x))
{}
A::~A()
{
delete implementation_;
}
bool
A::Eq(const A& rhs) const
{
return implementation_->x_ == rhs.implementation_->x_;
}
在您的主文件中
#include "a.hpp"
int main()
{
A one(1);
A two(2);
return one.Eq(two);
}
因为所有实际代码都在实现文件中,所以您无法从其他类(仅包含头文件a.hpp)中看到它。为了清楚起见,我使用了原始指针,但在实际设置中,您将需要使用适当的智能指针。
关于c++ - C++中的数据抽象和二进制方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18550621/