如何基于模板创建不同的类实现

huangapple go评论63阅读模式
英文:

how to create diffrent class implemantations based off template

问题

以下是您提供的代码的翻译部分:

在我的animal.hpp文件中,我有这个模板类声明:

enum class ANIMAL_TYPE {
    DOG,
    CAT,
};

template <ANIMAL_TYPE T>
class animal {
public:
    void makeSound();
};

这是一个经典的示例,用于解释接口和继承,但我希望它在编译时知道,并且不是虚函数,因此我在animal.cpp文件中实现如下:

template <>
class Animal<ANIMAL_TYPE::DOG> {
public:
    void makeSound() {
        std::cout << "woof";
    }
};

template <>
class Animal<ANIMAL_TYPE::CAT> {
public:
    void makeSound() {
        std::cout << "MEOW";
    }
};

template class Animal<ANIMAL_TYPE::DOG>;
template class Animal<ANIMAL_TYPE::CAT>;

然后,在主文件中,我这样使用它:

#include <animal.hpp>

int main() {
    Animal<ANIMAL_TYPE::DOG> doggy;
    doggy.makeSound();
    return 0;
}

但是,当我编译和链接时,我得到了一个链接错误:"undefined reference to Animal<(ANIMAL_TYPE)0>::makeSound"。

英文:

Let's say I have this template class declared in my animal.hpp file:

enum class ANIMAL_TYPE{
     DOG,
     CAT,
};

template &lt;ANIMAL_TYPE T&gt;
class animal{
public:
    void makeSound();
    };

Pretty classic example used in explanations of interfaces and inheritance, but I want it to be known at compile time, and not be a virtual function, so I implemented it like this in the animal.cpp file:

template &lt;&gt;
class Animal&lt;ANIMAL_TYPE::DOG&gt;{
public:
    void makeSound(){
         std::cout &lt;&lt; &quot;woof&quot;;
    }
};

template &lt;&gt;
class Animal&lt;ANIMAL_TYPE::CAT&gt;{
public:
    void makeSound(){
         std::cout &lt;&lt; &quot;MEOW&quot;;
    }
};

template class Animal&lt;ANIMAL_TYPE::DOG&gt;;
template class Animal&lt;ANIMAL_TYPE::CAT&gt;;

And this in the main file:

#include &lt;animal.hpp&gt;


int main(){
    Animal&lt;ANIMAL_TYPE::DOG&gt; doggy;
    doggy.makeSound();
    return 0;
}

But when I compile and link this, I get an error during linking "undefined reference to Animal&lt;(ANIMAL_TYPE)0&gt;::makeSound"

答案1

得分: 0

以下是翻译的内容:

而不是实例化类本身,您应该实例化方法。换句话说,不要这样做:

template <typename>
class Animal<ANIMAL_TYPE::DOG>{
public:
    void makeSound(){
         std::cout << "woof";
    }
};

template <typename>
class Animal<ANIMAL_TYPE::CAT>{
public:
    void makeSound(){
         std::cout << "MEOW";
    }
};

您应该这样做:

template <>
void Animal<ANIMAL_TYPE::DOG>::makeSound()
{
    std::cout << "woof";
}

template <>
void Animal<ANIMAL_TYPE::CAT>::makeSound()
{
    std::cout << "MEOW";
}

此外,我注意到您在animal.cpp底部有以下内容:

template class Animal<ANIMAL_TYPE::DOG>;
template class Animal<ANIMAL_TYPE::CAT>;

在这种情况下,它们没有任何效果,您可以将它们删除。

编辑: 好的,如果您想要有两个模板参数,一个是类型,一个不是类型,您需要在头文件中直接实例化类,因为它仍然是一个模板,而不是一个完整的实例化。

例如,假设之前的Animal类接受一个类型参数。

template <ANIMAL_TYPE T, typename R>
class Animal{
    public:
    void makeSound(R foo);
};

您将不得不像这样实例化它(请记住将其放在头文件中,因为它仍然是一个模板,而不是一个完整的实例化)。

template <typename R>
class Animal<ANIMAL_TYPE::DOG, R>{
    public:
    void makeSound(R foo)
    {
        std::cout << "woof";
    }
};

template <typename R>
class Animal<ANIMAL_TYPE::CAT, R>{
    public:
    void makeSound(R foo)
    {
        std::cout << "MEOW";
    }
};

希望这对您有所帮助。

英文:

Instead of instantiating the classes themselves, you should be instantiating the methods. In other words, instead of doing this:

template &lt;&gt;
class Animal&lt;ANIMAL_TYPE::DOG&gt;{
public:
    void makeSound(){
         std::cout &lt;&lt; &quot;woof&quot;;
    }
};

template &lt;&gt;
class Animal&lt;ANIMAL_TYPE::CAT&gt;{
public:
    void makeSound(){
         std::cout &lt;&lt; &quot;MEOW&quot;;
    }
};

You should be doing this:

template &lt;&gt;
void Animal&lt;ANIMAL_TYPE::DOG&gt;::makeSound()
{
    std::cout &lt;&lt; &quot;woof&quot;;
}

template &lt;&gt;
void Animal&lt;ANIMAL_TYPE::CAT&gt;::makeSound()
{
    std::cout &lt;&lt; &quot;MEOW&quot;;
}

Also, I've noticed that you have this at the bottom of animal.cpp.

template class Animal&lt;ANIMAL_TYPE::DOG&gt;;
template class Animal&lt;ANIMAL_TYPE::CAT&gt;;

Those have no effect in this case, you can just remove them.

EDIT: Okay, so if you want to have two template arguments, one of which is a type, and one that is not a type, you will need to directly instantiate the class, in the header because it's still a template, not a complete instantiation.

For example, let's say that the Animal class from before takes in a type argument.

template &lt;ANIMAL_TYPE T, typename R&gt;
class Animal{
    public:
    void makeSound(R foo);
};

You will have to instantiate it like this (Remember to put this in the header file, as it is still a template and not a complete instantiation).

template &lt;typename R&gt;
class Animal&lt;ANIMAL_TYPE::DOG, R&gt;{
    public:
    void makeSound(R foo)
    {
        std::cout &lt;&lt; &quot;woof&quot;;
    }
};

template &lt;typename R&gt;
class Animal&lt;ANIMAL_TYPE::CAT, R&gt;{
    public:
    void makeSound(R foo)
    {
        std::cout &lt;&lt; &quot;MEOW&quot;;
    }
};

Hopefully, this is helpful.

huangapple
  • 本文由 发表于 2023年7月31日 22:55:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76804826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定