替代转换 return 基 class 受保护方法的指针?

Alternative to casting return pointer of base class protected method?

我想出了一个 class,它使用受保护的嵌套结构,旨在派生 classes 来扩充该结构。为此,我声明了一个用于分配结构的虚拟方法。

现在,基础 class 在 processSomeData 中做了一些不平凡的工作,我希望派生 class 重用它。

这导致以下内容:

class A
{
public:
    virtual void doProcessing(); // uses processSomeData()

protected:
    struct someData
    {
        virtual ~someData() {};

        // data members
    };

    virtual someData* processSomeData(); // uses allocateSomeData()
    virtual someData* allocateSomeData();
};

class B : public A
{
public:
    virtual void doProcessing()
    {
        derivedData* myData =
            static_cast<derivedData*>(A::processSomeData()); // *** seems a little suspect

        // do work on the additional data members in myData
    }

protected:
    struct derivedData : public someData
    {
        // more data members
    };

    virtual derivedData* allocateSomeData();
};

因为allocateSomeData被覆盖了,我知道A::processSomeData返回一个someData*指向derivedData,所以static_cast绝对安全。

就是说,当其他一切看起来都非常合理时,我不得不从基础转换为派生感觉有点不对劲。
有没有 better/proper 方法可以做到这一点,而不使用强制转换?还是我必须重新设计我的 classes/structs?

这是因为编译器不确定 processSomeData 使用 allocateSomeData 来创建 someData 结构。就编译器所知的 someData 而言,从 processSomeData 返回的可能只是 someData 的一个实例。 derivedData 是 someData 但不是相反。

我通过将嵌套的 class 移出并将其作为模板参数解决了这个问题,因为我永远不会同时使用 someDataderivedData

struct someData
{
    virtual ~someData() {};

    // data members
};

template <typename DataType = someData>
class A
{
public:
    virtual void doProcessing(); // uses processSomeData()

protected:
    typedef DataType myDataType;

    virtual myDataType* processSomeData(); // uses allocateSomeData()
    virtual myDataType* allocateSomeData();
};

struct derivedData : public someData
{
    // more data members
};

class B : public A<derivedData>
{
public:
    virtual void doProcessing()
    {
        myDataType* myData = A::processSomeData();

        // do work on the additional data members in myData
    }

protected:

    virtual myDataType* allocateSomeData();
};

虽然嵌套 class 看起来是封装信息的好方法,但似乎不值得在类型安全和性能之间进行权衡。

这个 answer 在我做出更改后不久发现的,似乎在某种程度上证明了我的决定。

虽然模板参数是一个很好的方法,但让我为另一个解决方案投票。

首先我们将 processSomeData 移动到嵌套的 someData 结构中,使其保持虚拟。它的实现完成了 someData 及其派生的 classes 的所有共同工作。我们还有一个新的受保护的虚函数,称之为furtherProcess。对于 someData 它是空的。对于每个派生 class,它会处理任何需要的东西。 someData::processSomeData() 的最后一行是 furtherProcess().

这种在末尾使用挂钩函数避免了 Call Super 原始设置中隐含的代码味道,这种情况经常出现在这些向下转换中。