Alternative to casting return pointer of base class protected method?
我想出了一个使用受保护的嵌套结构的类,打算让派生类扩充该结构。为此,我声明了一个用于分配结构的虚拟方法。
现在,基类在
这将导致以下情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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(); }; |
因为
这就是说,当其他一切看起来都很干净的时候,我觉得有点不该从一个基地扔到衍生基地。有没有更好/正确的方法来做到这一点,而不使用石膏?还是必须重新设计类/结构?
虽然模板参数是一个很好的方法,但是让我投票选择另一个解决方案。
首先,我们将
这种在末尾使用hook函数可以避免a href="https://en.wikipedia.org/wiki/call_super"rel="nofollow">call super/aa代码在原始设置中散发出暗含的气味,这在这些降级中经常会看到。
这是因为编译器不确定processSomeData是否使用allocateSomeData创建SomeData结构。据编译器所知,从processSomeData返回的SomeData很可能只是SomeData的一个实例。派生数据是一些数据,但不是反过来。
我通过将嵌套类移出并使其成为模板参数来解决这个问题,因为我永远不会同时使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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(); }; |
虽然嵌套类看起来是一种封装信息的好方法,但它似乎不值得在类型安全性和性能之间进行权衡。
这个答案,在我做出改变后不久发现的,似乎在一定程度上证明了这个决定的正确性。