替代转换 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 移出并将其作为模板参数解决了这个问题,因为我永远不会同时使用 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();
};
虽然嵌套 class 看起来是封装信息的好方法,但似乎不值得在类型安全和性能之间进行权衡。
这个 answer 在我做出更改后不久发现的,似乎在某种程度上证明了我的决定。
虽然模板参数是一个很好的方法,但让我为另一个解决方案投票。
首先我们将 processSomeData
移动到嵌套的 someData
结构中,使其保持虚拟。它的实现完成了 someData
及其派生的 classes 的所有共同工作。我们还有一个新的受保护的虚函数,称之为furtherProcess
。对于 someData
它是空的。对于每个派生 class,它会处理任何需要的东西。 someData::processSomeData()
的最后一行是 furtherProcess()
.
这种在末尾使用挂钩函数避免了 Call Super 原始设置中隐含的代码味道,这种情况经常出现在这些向下转换中。
我想出了一个 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 移出并将其作为模板参数解决了这个问题,因为我永远不会同时使用 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();
};
虽然嵌套 class 看起来是封装信息的好方法,但似乎不值得在类型安全和性能之间进行权衡。
这个 answer 在我做出更改后不久发现的,似乎在某种程度上证明了我的决定。
虽然模板参数是一个很好的方法,但让我为另一个解决方案投票。
首先我们将 processSomeData
移动到嵌套的 someData
结构中,使其保持虚拟。它的实现完成了 someData
及其派生的 classes 的所有共同工作。我们还有一个新的受保护的虚函数,称之为furtherProcess
。对于 someData
它是空的。对于每个派生 class,它会处理任何需要的东西。 someData::processSomeData()
的最后一行是 furtherProcess()
.
这种在末尾使用挂钩函数避免了 Call Super 原始设置中隐含的代码味道,这种情况经常出现在这些向下转换中。