C++中的多态和获取对象类型 [英] Polymorphism and get object type in C++

查看:64
本文介绍了C++中的多态和获取对象类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有 4 个类,B,C,D,E,它们继承自 A(抽象基类).另外我有一个 A* 类型的容器(std::vector),它的内容指向B,C,D,E 对象.以下是一些规则:如果 B 对象和 C 对象交互,它们会从向量中移除,并在它们的位置创建 D 对象.

Let's say that I have 4 classes, B,C,D,E that inherit from A(abstract base class). Also I have a container (std::vector) of type A* whose contents point to either of B,C,D,E objects. Here are some rules: If a B object and a C object interact, they get removed from the vector and in their place a D object gets created.

另外,C + D = E

现在,假设我随机选择上述矢量内容之一;为了实现交互机制,我将如何知道哪个对象属于哪种类型?

Now, suppose that I randomly choose one of said vector contents; how would I go about knowing which object is of which type, in order to implement an interaction mechanic?

注意:我不希望使用 typeid 运算符、动态转换或标志.还有其他解决方案吗?

NOTE: I do not wish to use the typeid operator, a dynamic cast or flags. Any other solutions?

这是一些代码

#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;
}

我将如何实现交互功能?

How would I implement the interact function(s) ?

推荐答案

你可以使用虚函数来做多分派

You may use virtual functions to do the multiple dispatch

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
}

这篇关于C++中的多态和获取对象类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆