c++ - 重构指向某种形式模板的函数指针

标签 c++ templates refactoring function-pointers

请耐心等待我转储以下简化代码:(我将在下面描述问题。)

class CMyClass
{
    ...
private:
 HRESULT ReadAlpha(PROPVARIANT* pPropVariant, SomeLib::Base *b);
 HRESULT ReadBeta(PROPVARIANT* pPropVariant, SomeLib::Base *b);

 typedef HRESULT (CMyClass::*ReadSignature)(PROPVARIANT* pPropVariant, SomeLib::Base *b);

 HRESULT TryFormats(ReadSignature ReadFormat, PROPVARIANT* pPropVariant);
};


inline HRESULT CMyClass::ReadAlpha(PROPVARIANT* pPropVariant, SomeLib::Base *b)
{
 if (b)
 {
     // got a valid Base. Handle generic stuff here.
     SetStuff(pPropVariant, b->someInt);
     return S_OK;
 }

 return (b != NULL) ? 0 : -1;
}

inline HRESULT CMyClass::ReadBeta(PROPVARIANT* pPropVariant, SomeLib::Base *b)
{
 if (b)
 {
  SomeLib::FormatA *fa;
  SomeLib::FormatB *fb;

  if ( fa = dynamic_cast<SomeLib::FormatA*>( b ) )
  {
   // specific code for FormatA
   SetStuff(pPropVariant, fa->getVersion());
   return S_OK;
  }
  else if ( fb = dynamic_cast<SomeLib::FormatB*>( b ) )
  {
   // specific code for FormatB
   SetStuff(pPropVariant, fb->valueForB);
   return S_OK;
  }
 }

 return (b != NULL) ? 0 : -1;
}

inline HRESULT CMyClass::TryFormats(ReadSignature ReadFormat, PROPVARIANT* pPropVariant)
{
 HRESULT hr;
 if (FAILED(hr = (this->*ReadFormat)(pPropVariant, _pFile->formatA())))
  if (FAILED(hr = (this->*ReadFormat)(pPropVariant, _pFile->formatC())))
   hr = (this->*ReadFormat)(pPropVariant, _pFile->formatD());

 return hr;
}

我最终像这样调用这段代码:

hr = TryFormats(&CMyClass::ReadAlpha, pPropVar);

现在...问题是这太笼统和受限了,尤其是现在我正在尝试重构此代码以用于其他一些项目。所以,这意味着我想放置 ReadXxx另一个源文件中的代码并以某种方式滥用模板。 TryFormats留在类里面,因为不同的类(class)有不同的阅读格式。

由于 dynamic_cast<Derived*>,我目前的方法注定会失败Base 中没有的功能需要类,并且由于我可能需要在一节课中阅读多达 5 种不同的格式,所以我真的不想拖入我一开始不需要的格式。 (例如,参见上面的 CMyClass 不支持 SomeLib::FormatB ,但 ReadBeta() 需要支持它,从而强制编译器编译所有相关信息。)总共,我有大约 10 种不同的格式像这样'支持'。

如何正确重构这段代码?我不想重写 Base每个后代的功能,我也不想将派生的特定信息放入只接受 Base 的函数中.

我已经尝试了一些东西,但我设法从我的编译器中挤出的是错误的彩虹。为了不让这里的人对我的尝试感到困惑,我想我会给出我的(简化的)原始工作代码,并让专家们就如何做到这一点得出他们自己的结论。实际上,其中大约有 50 个 ReadXxx功能,但它们要么遵循 ReadAlpha 的一般结构或 ReadBeta以上功能。因此,如果有人可以告诉我如何执行这些操作,我就可以毫无问题地转换我的实际代码。 (我想我也需要更改 TryFormats() 定义,这也没问题 - 我只是希望有人能告诉我如何正确重构上述示例。)

谢谢,对于这个很长很长的问题,我深表歉意。

最佳答案

好吧,我之前的visitor方法已经成为历史。 我将向您发布您可以使用的小型工作程序的完整文本。 假设

_pFile->formatA()
_pFile->formatC()
_pFile->formatD()

全部声明为

FormatA* formatA()
FormatC* formatC()
FormatD* formatD()

换句话说,返回类型在编译时是已知的,这种模板化的方法可能适合你。而且它既不涉及函数指针也不涉及动态向下转型

//////////////////////////////////////////////////////////////////
// this section is for testing
class   Base    
{
public:
    void ExecuteBase()
    {
        cout << "Executing Base" << endl;
    }
};

class   FormatA :   public Base
{
public:
    void    ExecuteAAlpha()
    {
        cout << "Executing A Alpha" << endl;
    }

    void    ExecuteABeta()
    {
        cout << "Executing A Beta" << endl;
    }
};

class   FormatB : public Base
{
public:
    void    ExecuteBAlpha()
    {
        cout << "Executing B Alpha" << endl;
    }

    void    ExecuteBBeta()
    {
        cout << "Executing B Beta" << endl;
    }
};

FormatA* GetFormatA()
{
    static FormatA cl;
    return &cl;
}

FormatB* GetFormatB()
{
    static FormatB cl;
    return &cl;
}
//////////////////////////////////////////////////////////////////




//////////////////////////////////////////////////////////////////
// now begins real code
struct AlphaReader  {};
struct BetaReader {};
template <typename READER_TYPE> struct TypeConverter    {};


class   MyClass
{
public:
    template <typename READER_TYPE>
    int TryFormats(const READER_TYPE&)
    {
        TryFormatsImplementation(TypeConverter<READER_TYPE>(), GetFormatA());
        TryFormatsImplementation(TypeConverter<READER_TYPE>(), GetFormatB());

        return 0;
    }

private:
    int     TryFormatsImplementation(const TypeConverter<AlphaReader>&, Base* pFormat)
    {
        // here you will call you ReadAlpha which requires Base only
        // code below is for testing

        cout << "Executing Alpha Reader for Base" <<endl;
        pFormat->ExecuteBase();
        return 1;
    }

    int     TryFormatsImplementation(const TypeConverter<BetaReader>&, FormatA* pFormat)
    {
        // here you will call you ReadBeta for FromatA,
        // code below is for testing

        cout << "Executing Beta Reader for FormatA" <<endl;
        pFormat->ExecuteABeta();
        return 3;
    }

    int     TryFormatsImplementation(const TypeConverter<BetaReader>&, FormatB* pFormat)
    {
        // here you will call you ReadBeta for FromatB,
        // code below is for testing

        cout << "Executing Beta Reader for FormatB" <<endl;
        pFormat->ExecuteBBeta();
        return 4;
    }
};


int main()
{
    MyClass cl;

    cl.TryFormats(AlphaReader());
    cl.TryFormats(BetaReader());

    cin.get();
}

运行此程序后,我得到以下正确输出:

Executing Alpha Reader for Base
Executing Base
Executing Alpha Reader for Base
Executing Base
Executing Beta Reader for FormatA
Executing A Beta
Executing Beta Reader for FormatB
Executing B Beta

关于c++ - 重构指向某种形式模板的函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1770808/

相关文章:

C++模板矩阵类——方阵特化

python - 重构错误处理并在 Python 中获得正确的堆栈跟踪

c++ - C++ 中 NaN 的异常原因?极限接近零会导致 NaN 吗?

c++ - 我在编写一个控制台应用程序来创建一个简单的程序来解决退休金的数学方程式时遇到问题

c++ - C++中异常类的继承

c++ - 是否可以使用vector <T>作为值来定义unordered_map?

c++ - 遍历嵌套的 C++11 元组

function - Haskell 中的折叠实现

python - 接近重构

C++ 如何将字符串转换为指针?