替代基类保护方法的转换返回指针?

时间:2015-06-13 19:23:14

标签: c++ casting

我想出了一个使用受保护的嵌套结构的类,希望派生类能够扩充结构。为此,我声明了一个用于分配结构的虚方法。

现在,基类在processSomeData中完成了一些非常重要的工作,我希望派生类能够重用它。

导致以下内容:

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*的{​​{1}},因此static_cast肯定是安全的。

那就是说,当其他一切看起来都非常犹太时,我应该从一个基地投射出来,感觉有点偏离。 有没有更好/正确的方法来做到这一点,而不使用演员?或者我是否必须重新设计我的类/结构?

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

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

最后使用钩子函数避免了原始设置中隐含的Call Super代码气味,这种情况通常会出现在这些向下的情况下。

答案 2 :(得分:0)

我通过移动嵌套类并使其成为模板参数来解决问题,因为我永远不会同时使用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();
};

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

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