c++ - 确保指向父类(super class)的指针指向C++中某个子类的对象

标签 c++ casting polymorphism subclass

我有两个容器(分别称为A型和B型),它们都从父类型(称为AB)派生。父类具有Widget对象的链接列表。在我的Widget类中,我有一个指向其所在容器的指针。显然,这被声明为指向AB的指针。同样在widget类中,我有一个仅在widget的容器​​是A且它使用指向AB的指针时才适用的方法。但是,当然,我需要将其转换为A *。

我曾考虑过在AB中使该方法成为虚拟方法,并引发错误;然后在A中覆盖它,但这使我感到困扰,因为该方法仅适用于A,而在通用AB情况下没有意义。

我考虑过使用dynamic_cast将父指针转换为A *。但是我也读到这暗示了糟糕的类设计。处理此问题的首选方法是什么?

class Widget;

class AB
{
    private:
        Widget* firstWidget;   // first widget in a linked list, don't judge.
};

class A : public AB
{
    public:
        void methodSpecificToA() {}
};

class B : public AB {}; 

class Widget
{
    private:
        AB* container;
    public:
        void AWidgetMethod()
        {
            A* ac = static_cast<A*>(container);
            ac->methodSpecificToA();
        }

};

最佳答案

这些评论提到了一种不让基类提供某些派生类可能需要的所有虚拟方法的愿望。这种愿望是一件好事。让我们看看我是否可以提出一些替代方案。 (我没有断言是详尽无遗的。)请承认这些是通用的,因为问题涉及的上下文很少。所以我有点猜测。我不知道什么是给定方案的最佳选择。

在寻找替代方案之前,设计有什么问题?主要问题是Widget类对AB层次结构有所了解,然后根据此知识进行决策。您的类(class)彼此了解的越少,他们之间的隔离就越多。对于人们来说,隔离是不好的,但是对于类来说,这意味着更少的相互依赖性和更少的错误,而当其中一个类改变时,引入的错误也更少。理想情况下,Widget类知道通用的AB接口(interface),并且层次结构中没有其他内容。也许从Widget派生的类对从AB派生的类有所了解。或者可能不是。可以采用不同的方法。

说发生了什么,而不是该怎么做。 出现这种情况的原因之一是,小部件通过告诉容器做某事来响应某种刺激。有时,应该看一看容器可能需要做的所有事情,并将其与容器可能需要响应的所有事情进行比较。如果每个刺激一个,而不是每个 Action 一个,那么最终可能会得到一小段虚拟功能。另外,刺激功能应该适用于基类,而 Action 功能则可能不适用。 (例如,用于刺激的函数可能是WasPressed(Widget & widget)。)如果采用这种方法,则小部件通过告诉容器发生了刺激来响应某种刺激,让容器决定它需要做什么。在某些情况下,这本身会减少一个类(class)对另一类(class)的了解。在其他情况下,它似乎更人为设计(在这种情况下,不一定是个好主意)。

专门的类应该得到专门的数据。 好吧,并非总是如此。不过,有时还是值得多记账,以使代码在维护时保持健壮(也就是其他人在“改进”代码)。我正在考虑以下情况:调用methodSpecificToA的小部件知道其容器是A,因为它是某种类型的小部件。例如,滚动条会知道其父级是可滚动区域,因为这是唯一需要滚动条的容器。在这种情况下,值得让专用窗口小部件维护其自己的指向其容器的指针,并将其存储为A的指针。 (这是对您已经拥有的AB的指针的补充。)不需要强制转换,甚至可以将此特殊功能与“我的容器”概念分开。 (也许A应该具有两个基类:AB和一个定义methodSpecificToA的基类。如果执行此操作,则专用小部件将存储指向该新基类的指针。)

使用回调。 这个经典的方法可以使一个类不需要知道关于另一个类的任何知识。即使该窗口小部件不是专用的,它也可以工作,但是如果不需要很多回调,则它可以最好地工作。 (如果需要许多回调,则使用上面的“特殊数据”可能会更好。)使用回调时,将告知窗口小部件在发生某种刺激时调用某种function object,这就是它的作用。不知道会发生什么,也不需要指向其容器的指针。容器和窗口小部件如何交互的知识从窗口小部件转移到将窗口小部件放置在容器中的代码。 (这是设置回调的代码。)

关于这些建议,您可能会注意到的一件事是,它们都没有告诉您如何从指向methodSpecificToA的指针调用AB。这就是为什么我建议更深入地研究这种问题。一旦看到警告标记表明您可能存在设计缺陷,通常最好检查一下设计。整个设计,而不仅仅是国旗出现的一小部分。

关于c++ - 确保指向父类(super class)的指针指向C++中某个子类的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50975470/

相关文章:

c# - 如何反编译c++ dll?

C++ 帮助理解偏特化

c++ - Win API,每 X 秒更新一次静态控件

将 : uid_t to string, off_t 转换为字符串

objective-c - 将 int64_t 转换为 NSInteger

qt - 如何覆盖 Q_Property?

c++ - 当我使用 C++ win32 API 单击确定按钮时,如何隐藏当前窗口?

c# - 将 Combobox.SelectedItem 转换回 DateTime 会导致 "Specified cast is not valid."

ruby-on-rails - RoR : has_one "or the other"?(或者,没有继承的多态性。)

java - 如何从父类和子类的相同方法返回泛型类型