【问题标题】:How to make a common reusable function with different class types to reduce the code duplication using C++如何使用 C++ 制作具有不同类类型的通用可重用函数以减少代码重复
【发布时间】:2020-11-17 16:38:37
【问题描述】:

我正在从不同的类和文件中调用以下函数,如下所示。 并且实现几乎相似。但它正在各自的类构造函数中初始化。

我可以为所有类的以下代码创建一个通用函数吗 然后在调用的时候,可以根据类初始化并返回对象吗?

下面是所有类的实现几乎相似的函数。我在大约 10 个地方都有类似的实现。

有人可以建议我创建通用可重用函数的更好方法吗?

1.

shared_ptr<CTestOneImpl> COneImpl::createTestObject(const string& f_strSFID, short f_nID,
                                                        bool f_bIsVerified,
                                                        bool f_bIsProcessed)
{
shared_ptr<CTestOneImpl> l_pTestObj = nullptr;
l_pTestObj = make_shared<CTestOneImpl>(f_nID, f_strSFID,
                                                    f_bIsVerified, f_bIsProcessed,
                                                    this);
 return l_pTestObj;
}
shared_ptr<CTestTwoImpl> CTwoImpl :: createTestObject(string f_hStrSFID, long f_nID,
                                                          bool f_bIsVerified,
                                                          bool f_bIsProcessed)
{
shared_ptr<CTestTwoImpl> l_pTestObj = nullptr;
l_pTestObj = make_shared<CTestTwoImpl>(f_nID, f_hStrSFID, f_bIsVerified
                                                , f_bIsProcessed, this);
return l_pTestObj;
}
shared_ptr<CTestThreeImpl> CThreeImpl ::createTestObject(const string& f_strSFID,
                                                     const string& f_nID,
                                                     bool f_bIsVerified,
                                                     bool f_bIsProcessed)
{
shared_ptr<CTestThreeImpl> l_pTestObj = nullptr;
l_pTestObj = make_shared<CTestThreeImpl>(f_nID,
                                              f_strSFID,
                                              f_bIsVerified,
                                              f_bIsProcessed,
                                              this);
return l_pTestObj;
}

使用基于输入的模板化类更新代码:

.h 文件

#include <iostream>
#include <list>

template <typename RetType, typename Args1, typename Args2, typename Args3>
class CTestImpl
{
public:
    CTestImpl(std::string f_lCallIdentifier, bool f_bIsVerified,
         bool f_bIsProcessed);

private:
    std::shared_ptr<RetType>
    createTestObject(Args1&& f_strSFID, Args2&& f_bIsVerified, Args3&& f_bIsProcessed);

public:
    void handleEvents(const std::string& f_eCallEvent, const std::string& f_strSFID);
};

.Cpp 文件

#include "TestImpl.h"

template <typename RetType, typename Args1, typename Args2, typename Args3>
// error: C2976: 'CTestImpl': too few template arguments
std::shared_ptr<RetType> CTestImpl<RetType>::createTestObject(Args1&& f_strSFID, Args2&& f_bIsVerified, Args3&& f_bIsProcessed)
// error: C2244: 'CTestImpl::createTestObject': unable to match function definition to an existing declaration
{
    return std::make_shared<RetType>(std::forward<Args1>(f_strSFID),
                                              std::forward<Args1>(f_bIsVerified),
                                              std::forward<Args1>(f_bIsProcessed));
}

//error: C2955: 'CTestImpl': use of class template requires template argument list
void CTestImpl::handleEvents(const std::string& f_eCallEvent, const std::string& f_strSFID)
{
    // error: C2509: 'handleEvents': member function not declared in 'CTestImpl'
    shared_ptr<CTestImpl> l_hCallObj = nullptr;
    l_hCallObj = createTestObject(f_strSFID, true, false);
}

【问题讨论】:

  • 顺便说一句:调用一个函数的用例是什么,它实际上什么都不做,只是将所有参数转发给另一个函数。如果您将 createTestObject() 替换为 make_shared() 其他任何内容都不会改变。但是,如果您的 create func 中有任何有用的东西,您只需将其设为模板即可。这将保护源代码,生成的程序集不应更改,这意味着您没有为 prog 提供安全的代码大小。
  • 你可以使用GPP生成C++代码

标签: c++ c++11 c++14


【解决方案1】:

不确定你到底想要什么……但是……如下呢?

template <typename RetType>
shared_ptr<RetType> BaseClass::createTestObject (std::string const & f_strSFID,
                                                 short f_nID,
                                                 bool f_bIsVerified,
                                                 bool f_bIsProcessed)
{ return std::make_shared<RetType>(f_nId, f_strSFID, f_bIsVerified, f_bIsProcessed, this); }

或者,如果您按照RetType 构造函数所需的相同顺序将参数传递给createTestObject()(也为this),也许更好

template <typename RetType, typename ... Args>
shared_ptr<RetType> BaseClass::createTestObject (Args && ...as)
{ return std::make_shared<RetType>(std::forward<Args>(as)...)); }

但是,此时,您可以直接拨打std::make_shared()

【讨论】:

  • 感谢@max66 的宝贵意见。根据您的输入,我创建了一个模板化类。但我遇到了一些错误。我已经用更改更新了原始帖子。请帮我解决错误。
  • @JohnPaulCoder - 建议:从不 (never!!!) 在 .cpp 文件中定义模板类或函数。 Always (always!!!) 声明在头文件中定义模板内容。更多参考请参见this question
  • @JohnPaulCoder - 第二个建议:当您“遇到一些错误”时,将它们转录到问题中。
  • 感谢@max66 的宝贵意见。
【解决方案2】:

你没有提供足够的信息,所以我会做一些假设。

假设

  1. 所有类的构造函数具有相同的签名。您对make_shared 的所有调用都传递了相同的变量,所以我认为是这种情况。
  2. 所有类都有类似的功能。您说实现几乎相同,所以我们假设是这种情况。
  3. 您有一些方法来区分这些类。通过了解有关您正在做的事情的更多信息(可能发布某些类的标题),这种假设会得到最好的帮助。出于本示例的目的,假设您知道在运行时您将要实例化一个“TestOne”、“TestTwo”或“TestThree”对象。我相信人们会解释说这不是最好或最有效的想法,他们会是正确的,但这是现实生活,有截止日期,这些课程似乎是测试课程,所以这应该足够了.

解决方案 使用多态性。

/**
 * This is an interface that all of your test classes will need to implement.
 */
class ITest {
public:
   ~virtual ITest() = default;
   virtual void CommonMethod(...) = 0;
};

class CTestOneImpl : public ITest {
   void CommonMethod(...) override;
};

假设您的所有 3 个(或多个)类的设置都像上面那样,您现在可以创建一个工厂类,这会让一些人感到难过。

class TestObjectFactory {
   enum class TestType{
       TestOne,
       TestTwo, 
       TestThree
   };

   static std::shared_ptr<TestObject> MakeTestObject(TestType &t, ...) {
       switch(t) {
       case(TestOne): return std::make_shared<CTestOneImpl>(...);
       ....
       default: return nullptr;
       }
   }
};

所以当你想要一个 CTestOneImpl 时,你只需调用 auto test_obj_ptr = TestObjectFactory::MakeTestObject(TestObjectFactory::TestType::TestOne, ...)

希望这能回答您的问题,如果不能,请提供更多信息。

【讨论】:

  • 嗨@Josh A,感谢您的输入: 1. 类的构造函数没有相同的签名。在某些类中,参数大小也不同。 2. 所有类中的类似功能。 3. 你是对的,在运行时,会想要实例化“TestOne”、“TestTwo”或“TestThree”对象。
猜你喜欢
  • 1970-01-01
  • 2013-01-28
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多