多态性并获取C++中的对象类型
假设我有4个类,B,C,D,E
从A
(抽象基类)继承。 另外,我有一个A*
类型的容器(std::vector
),其内容指向 B,C,D,E
对象。 这里有一些规则: 如果一个B
对象和一个C
对象相互作用,它们将从矢量中移除,并在它们的位置创建一个D
对象。多态性并获取C++中的对象类型
此外,C + D = E
现在,假设我随机选择的所述向量内容之一;为了实现交互机制,我该如何去了解哪个对象是哪种类型的?
注:我不希望使用typeid
运算符,动态转换或标志。其他解决方案?
下面是一些代码
#include <iostream>
class A {
protected:
int v;
public:
A(){}
~A(){}
};
class B :public A {
public:
B(){}
~B(){}
};
class C : public A {
public:
C(){}
~C(){}
};
class D : public A {
public:
D(){}
~D(){}
};
class E : public A {
public:
E(){}
~E(){}
};
int main()
{
std::vector<A*> container;
return 0;
}
我将如何实现交互功能(S)?
您可以使用虚拟函数做多分派
struct B;
struct C;
struct D;
struct E;
struct A
{
virtual ~A() = default;
virtual std::unique_ptr<A> interactWithA(const A&) const = 0;
//protected:
virtual std::unique_ptr<A> interactWithB(const B&) const = 0;
virtual std::unique_ptr<A> interactWithC(const C&) const = 0;
virtual std::unique_ptr<A> interactWithD(const D&) const = 0;
virtual std::unique_ptr<A> interactWithE(const E&) const = 0;
};
// Your interact rules
template <typename LHS, typename RHS>
std::unique_ptr<A> interact(const LHS&, const RHS&) { return nullptr; }
// Note that definitions and declarations must be split in reality
// to be able to compile it
std::unique_ptr<A> interact(const B&, const C&) { return std::make_unique<D>(); }
std::unique_ptr<A> interact(const C&, const D&) { return std::make_unique<E>(); }
// Maybe the reflexive case, C/B D/C ?
// The derived classes
struct B : A
{
std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithB(*this); }
// Even if code look similar for other inherited class
// the difference is in the runtime type of the objects are known.
std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); }
};
struct C : A
{
std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithC(*this); }
std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); }
};
struct D : A
{
std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithD(*this); }
std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); }
};
struct E : A
{
std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithE(*this); }
std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); }
std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); }
};
然后
std::vector<std::unique_ptr<A>> v /* = .. */;
auto a = v[i]->interactWithA(*v[j]);
if (a) {
// Remove v[i] and v[j]
// Insert a
}
你的问题听起来像一个糟糕的抽象。所以实际上你并没有解决正确的问题。当您不需要知道对象的确切类型时,应该使用继承,而应该依赖运行时多态。
你可以烘烤一些标志,比如虚拟函数,它将返回每种类型的标识,但是相当有效,而不是解决方案。弄错它也很容易。
class A
{
...
virtual int get_id() = 0;
}
变种
相反多态性,如果类型是固定的(例如,你不打算添加或删除类),你可以使用std::variant<>
(C++ 17)或升压。变种。要与之互动,您需要使用访问者并致电std::visit()
。可能会更难与它互动,但在我看来,它更适合作为你所描述的问题的解决方案。
还有别的办法吗?一个不需要标志或std :: variant? –
@JohnLannister,你不会提供任何细节。我可以写信给你:“我现在在吃巧克力,猜猜我吃的是什么巧克力?”。 ABCDE没有任何意义。你对这个问题的描述也不是 – Incomputable
而不是描述一些代码,请尝试创建一个[最小,完整,可验证的示例]( http://stackoverflow.com/help/mcve)并向我们展示。 –
什么是*“互动”*!?你知道的物品的位置如何在他们*“互动”*时被移除? – StoryTeller
关于“获取对象类型”,这确实不是一个好主意,尤其是在C++中,它会创建运行时开销。相反,使用虚拟功能来处理不同类别行为的设计通常是一种方法。 –