将基类作为参数传递给虚函数时避免使用 dynamic_cast

Posted

技术标签:

【中文标题】将基类作为参数传递给虚函数时避免使用 dynamic_cast【英文标题】:Avoid dynamic_cast when passing base class as a param to a virtual function 【发布时间】:2014-03-31 13:47:51 【问题描述】:

对于这个简单但重要的案例,我找不到明确的答案。 (如果有人向我推荐答案,我将不胜感激)。

假设我有两种继承:A 类是 B 类的基类,C 类是 D 类的基类,并做额外的工作(知道它实际上是指向 D 的指针)。

现在假设 A 类有一个虚函数 'foo',它接受一个指向 C 的指针作为参数。我想要实现的是,每当 A 调用 'foo' 时,它的行为就好像它有一个指向C,而每当 B 调用 foo 时,它的行为就好像它得到了一个指向 D 的指针。

编译器允许我传递一个被初始化的对象:C* c = new D();,但在 'foo' 内,据我所知,没有办法告诉我们实际上在没有使用 dynamic_cast 的情况下得到了一个指向 D 的指针。

这是我的想法的草图:

class C ;
class D : C // has more functions ;


class A 

public:
    virtual void foo (C* c)  //do something with c* ;

;


class B : A 

public

    virtual void foo (C* c)  // call A::foo()
                              //do something with c knowing that c* as actually a D*
                             

;

为了实现我想要的,在 B::foo 中使用 dynamic_cast 似乎是不可避免的。我知道一般来说使用 dynamic_cast 意味着糟糕的 OOP 设计,因为它可能违反 LSP,但我想不出其他方法来完成我想要的。

我很想听听一些提议 - 也许有人会如何改变设计,或者甚至“dynamic_cast 是必要的”都可以。

我希望我的观点很清楚,如果没有 - 我会澄清我的问题。

更新:也许我之前应该提过它(顺便说一句,我不只是编造这个,我实际上不得不在大学里编写类似的东西),但是第五课的想法,说 E 将举行A类型的数组(或列表或其他),我有一个迭代这个数组的算法,并且对于 那里的每个元素都应该调用这个“foo”方法——如果类实际上是 A*,它应该像以前一样运行,如果是 B*,它应该执行 B 类的“foo”。

类似这样的:

//within class E
A** arrayOfAs; //(and B's)
for (int i = 0 ; i < lengthOfArray ; ++i ) 

    arrayOfAs[i]->foo(/*someObject*/);

谢谢!

【问题讨论】:

你知道你在使用私有继承吗?这里不能有LSP。 '在传递基类时避免 dynamic_cast ...' 选择更好的设计,问题已经闻起来了... 【参考方案1】:

要做你想做的事,你需要一个dynamic_cast in B::foo。 但是...如果您只能使用D 调用B::foo,则该函数 不应该超载A::foo。这样做违反了 LSP,并且更多或 less 违背了面向对象代码的目的。

【讨论】:

以上是关于将基类作为参数传递给虚函数时避免使用 dynamic_cast的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我有两个函数时编译器没有显示错误,一个将基类作为参数,一个将派生类作为参数?

如何将子类作为期望基类的函数的参数传递,然后将该对象传递给指向这些抽象类对象的指针向量?

将基类转换为派生类[重复]

将参数传递给超类构造函数

将参数传递给基类构造函数

EXC_BAD_ACCESS(code = 1,address = 0x0)当将std :: map作为参数传递给虚拟函数调用时发生