【问题标题】:Implementing a non template method defined in a template class实现模板类中定义的非模板方法
【发布时间】:2011-12-09 13:36:34
【问题描述】:

当我想定义在模板类中声明的方法,但该方法不依赖于模板参数时,我是否可以在包含文件中将其定义为:

template class<typename T>
void MyClass::myMethod()
{
   ...
}

或者我可以在 cpp 文件中将其定义为:

void MyClass::myMethod()
{
   ...
}

?

谢谢。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    你需要像这样定义你的方法:

    template class<typename T>
    void MyClass<T>::myMethod()
    {
        // Method Body
    }
    

    这样做的原因是该方法实际上依赖于模板参数。请记住,每个方法都可以访问特殊变量this;在方法调用期间this实际上是传递给方法的参数。 this 类型的变化取决于对象实例化期间指定的模板参数,因此,所有方法都必须是模板方法才能适应所有形式的this

    【讨论】:

    • 还有一个小问题,在这种方法中,有时需要直接取消引用 this 以确保包含的代码是依赖的,并避免拾取其他阴影 id。
    【解决方案2】:

    好吧,如果方法不依赖于模板参数,你只能通过继承 AFAIK 来做到这一点。

    缺点:更多代码 + 继承

    好处:生成的代码(少得多)取决于您的代码的哪些部分实际上是依赖于模板的。在下面的示例中,方法NonDependentMethod 将只生成一个程序集,而DependentMethod 将生成尽可能多的不同模板参数(在这种情况下只有一个,但是创建一个MyClass&lt;float&gt; 并且你有两个,等等)。

    #include <iostream>
    using namespace std;
    
    class MyClassBase
    {
    public:
        void NonDependentMethod();
    };
    
    template <class T> class MyClass : public MyClassBase
    {
    public:
        void DependentMethod(T param);
    };
    
    void MyClassBase::NonDependentMethod()
    {
        cout << "NonDependentMethod" << endl;
    }
    
    template<class T> void MyClass<T>::DependentMethod(T param)
    {
        cout << "DependentMethod " << param << endl;
    }
    
    int main() {
        // your code goes here
        MyClass<int> cls;
        cls.NonDependentMethod();
        cls.DependentMethod(2);
        return 0;
    }
    

    【讨论】:

    • 为什么继承被列为不利因素?您在哪个代码中认为它是负面的?
    • 它不是负数,但它确实有一点性能损失,因为需要在相关表中查找虚拟方法。此外,实例化派生类的每个实例都需要设置所述查找表等。
    • 您的示例中的虚拟方法在哪里?据我所知,虚拟模板方法仅在 C++20 中引入,因此,即使您尝试过,也无法在 2015 年实现。
    • 代码中也不需要using namespace std;。您已经输入了 21 个字符来避免以后输入 20 个字符,但随后根据标准库的实现打开了您的代码以防以后出现错误。
    • 您在这里遇到的实际问题是什么?我认为即使是我最初的答案也足以解释这两种方法的优缺点。对命名空间的挑剔与所提出的问题无关。
    【解决方案3】:

    放在头文件中。

    成员函数仍然是类模板的成员,你必须这样写:

    template <typename T> void MyClass<T>::myMethod() { /* ... */ }
    

    与所有模板成员函数一样,这实际上还不是真正的函数;当类模板被实例化时,它只生成一个真正的函数。因此,所有实例化模板的人都必须看到完整的模板定义,而通常的做法是将所有内容都放在标题中。

    (请注意,类模板的成员函数本身被视为函数模板,您实际上可以对它们进行专门化:template &lt;&gt; void MyClass&lt;int&gt;::myMethod() { }。)

    【讨论】:

    • 呃?你确定注释部分吗?这听起来不对,例如因为您可以创建类模板的部分特化,但不能创建函数/方法模板。
    • 哦,哇,它实际上抱怨带有部分专业化的不完整类型。很高兴知道。
    【解决方案4】:

    你需要这样做:

    template class<typename T>
    void MyClass<T>::myMethod()
    {
       ...
    }
    

    模板化的不是方法,而是类。

    您可以在非模板类中使用模板方法,在模板类(您的情况)中使用非模板方法,在模板类中使用模板方法,当然在非模板类中也可以使用非模板方法。模板类。

    【讨论】:

      【解决方案5】:

      您必须以其他方式定义它。方法本身可能不(直接)依赖于模板参数,但它所属的类肯定依赖,不是吗?因此,该方法也间接依赖于模板参数:

      template class<typename T>
      void MyClass<T>::myMethod()
      {  //       ^^^ -- note
         ...
      }
      

      【讨论】:

        猜你喜欢
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        • 2020-12-27
        • 1970-01-01
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多