我想出了一个使用受保护的嵌套结构的类,希望派生类能够扩充结构。为此,我声明了一个用于分配结构的虚方法。
现在,基类在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肯定是安全的。
那就是说,当其他一切看起来都非常犹太时,我应该从一个基地投射出来,感觉有点偏离。 有没有更好/正确的方法来做到这一点,而不使用演员?或者我是否必须重新设计我的类/结构?
答案 0 :(得分:1)
这是因为编译器不确定processSomeData使用allocateSomeData来创建someData结构。就编译器知道someData而言,从processSomeData返回的内容可能只是someData的一个实例。 derivedData是someData但不是反过来。
答案 1 :(得分:1)
虽然模板参数是一个很好的方法,但我可以投票给另一个解决方案。
首先,我们将processSomeData
移动到嵌套的someData
结构中,使其保持虚拟状态。它的实现完成了someData
及其派生类的所有共同工作。我们还有一个新的受保护虚拟函数,称之为furtherProcess
。对于someData
,它是空的。对于每个派生类,它处理所需的任何内容。 someData::processSomeData()
的最后一行是furtherProcess()
。
最后使用钩子函数避免了原始设置中隐含的Call Super代码气味,这种情况通常会出现在这些向下的情况下。
答案 2 :(得分:0)
我通过移动嵌套类并使其成为模板参数来解决问题,因为我永远不会同时使用someData
和derivedData
。
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似乎在某种程度上证明了这一决定。