c++ - 决定将哪个派生类作为参数传递

标签 c++ inheritance argument-passing

我正在为当前的设计而苦苦挣扎,想知道是否有可能在不使用转换方法的情况下决定调用哪个方法。假设我有一个基础 Fence 类。

目前,我的 worker 知道如何 build 木栅栏以及如何 build 倒钩铁丝网。他们可以将两个栅栏加在一起……但到目前为止,他们只学会了如何将木栅栏与木栅栏连接起来,以及如何将带倒钩的有线的与带倒钩的有线的连接起来。

但是他们可能会学到更多,Fence 类有一个虚拟的 addFence(const Fence& fence) 方法。

因为我想避免任何转换方法,所以我尝试在两个类中添加特殊的 addFence() 方法。这是一个例子:

class Fence {
public:
    virtual void addFence(const Fence& fence) = 0;
    ...
};

class BarbWireFence : public Fence {
public:
    ...
    void addFence(const Fence& fence) {
        //only add such a fence, if it is a barb wired one
    }
    void addFence(const BarbWireFence& fence) {
        //continue the fence with the given one
    }
};

class WoodenFence : public Fence {
public:
    ...
    void addFence(const Fence& fence) {
        //only add the fence, if it is a wooden one
    }
    void addFence(const WoodenFence& fence) {
        //continue the fence with the given one
    }
};

现在我想做类似的事情

Fence *woodenFence1 = new WoodenFence();
Fence *woodenFence2 = new WoodenFence();
woodenFence1->addFence(*woodenFence2);

但由于运行时决定我有什么样的栅栏,我只有基本 Fence* 指针以及基本 class Fence 的定义用于最后一行。

那么有没有更好的实现来“自动”决定我有什么样的围栏?还是我应该使用完全不同的设计?

最佳答案

欢迎来到binary methods的精彩世界| .

这个问题没有令人满意的解决方案。您可能想了解 double dispatch和它更正式的兄弟the Visitor pattern .这两件事基本上是一样的,只是呈现方式略有不同。在最简单的情况下,您可以这样做:

class WoodenFence;
class BarbWireFence;

class Fence {
public:
    virtual void addFence(const Fence& fence) = 0;
    virtual void addMe(BarbWireFence& fence) const = 0;
    virtual void addMe(WoodenFence& fence) const = 0;
    ...
};


class BarbWireFence : public Fence {
public:
    ...
    void addFence(const Fence& fence) {
      fence->addMe(*this);
    }
    void addMe(BarbWireFence& fence) const {
      fence->addBarbWireFence(*this);
    }
    void addMe(WoodenFence& fence) const {
      throw error("bad fence combo");
    }

    void addBarbWireFence(const BarbWireFence& fence) {
      // actually add fence...        
    }
};

class WoodenFence : public Fence {
public:
    ...
    void addFence(const Fence& fence) {
      fence->addMe(*this);
    }
    void addMe(BarbWireFence& fence) const {
      throw error("bad fence combo");
    }
    void addMe(WoodenFence& fence) const {
      fence->addWoodenFenceFence(*this);
    }

    void addWoodenFence(const WoodenFence& fence) {
      // actually add fence...        
    }

    ...
};

您可以想出当您添加 10 种其他栅栏类型时会发生什么。

人们可能会采取完全不同的方向,即模板化整个业务并摆脱 Fence 基类,因为它不提供类型安全的接口(interface)。

class BarbWireFence {
public:
...
void addSimilarFence(const BarbWireFence& fence) {
    //continue the fence with the given one
    }
};

class WoodenFence {
public:
...
void addSimilarFence(const WoodenFence& fence) {
    //continue the fence with the given one
    }
};

template <typename Fence>
void addFence (Fence& f1, const Fence& f2) {
   f1->addSimilarFence(f2);
}

关于c++ - 决定将哪个派生类作为参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26590251/

相关文章:

c++ - Direct3D9 游戏 : Spaceship camera

java - 关系有一个,继承和类型转换

c++ - 在调用传递给模板函数的函数时调用指向成员函数的指针

c - 有多少种方法可以将char数组传递给C函数?

c++ - 将 unique_ptr 传递给库函数(FORTRAN 函数)

c++ - 我怎样才能让一个类实现一个接口(interface)....(C++)

C++ : friend function in a template class for operator<<

c++ - 使 C++ 中结构内部定义的枚举具有全局范围

c++ - 这是非多态继承的一个很好的理由吗?

c++ - 通过扩展添加可变性