Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用模板化函数实现多态性?_C++_Abstract Class_Function Templates - Fatal编程技术网

C++ 如何使用模板化函数实现多态性?

C++ 如何使用模板化函数实现多态性?,c++,abstract-class,function-templates,C++,Abstract Class,Function Templates,在我的项目中,我有一个带有接口的基本抽象类,派生类实现了接口。这些派生类具有接受不同类型参数的泛型函数。我使用函数模板在派生类中编写了这些泛型函数 我想将这些模板函数添加到基类的接口中。所以我可以实现多态性:在其他函数中接受基类,并在派生类中调用这些模板化函数 当我们使用普通函数时,我们会执行虚函数和重写,但不能使用模板函数执行虚函数 我试图在我的抽象基类中使用纯抽象模板函数,但它不起作用 这是一个小程序,具有我试图实现的功能,但由于virtual您试图使用声明为virtual的方法模板,因此无

在我的项目中,我有一个带有接口的基本抽象类,派生类实现了接口。这些派生类具有接受不同类型参数的泛型函数。我使用函数模板在派生类中编写了这些泛型函数

我想将这些模板函数添加到基类的接口中。所以我可以实现多态性:在其他函数中接受基类,并在派生类中调用这些模板化函数

当我们使用普通函数时,我们会执行虚函数和重写,但不能使用模板函数执行虚函数

我试图在我的抽象基类中使用纯抽象模板函数,但它不起作用


这是一个小程序,具有我试图实现的功能,但由于
virtual您试图使用声明为
virtual
的方法模板,因此无法编译。这是不可能的。另请参见相关问题

似乎您正在尝试创建某种序列化/反序列化机制。您希望将不同的结构(在不同的类中实现)转换为字节,并希望能够通过以某种方式解释字节来重新创建正确类型的对象

让我们首先处理序列化问题。通过为所有结构定义一个接口,并使用每个结构都应实现的序列化方法,您可以轻松解决此问题:

class Structure
{
public:
    virtual std::vector<uint8_t> ToBytes() = 0;

    // any other functionality common to all structures
};
希望这能有所帮助。

以下是我试图实现的行为的C版本:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace baseAbstractTemplates.NET {
    interface IObjectTransformer {
        TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes);
        ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure);
    };

    class ObjectTransformer1 : IObjectTransformer {

        #region Implementation of IObjectTransformerBaseAbstractClass

        public TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes) {
            throw new NotImplementedException();
        }

        public ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure) {
            throw new NotImplementedException();
        }

        #endregion

    }

    class ObjectTransformer2 : IObjectTransformer {

        #region Implementation of IObjectTransformerBaseAbstractClass

        public TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes) {
            throw new NotImplementedException();
        }

        public ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure) {
            throw new NotImplementedException();
        }

        #endregion

    }

    class Program {
        public static void CoutStructureBytes(IObjectTransformer objectTransformer) {
            var bytes = objectTransformer.ToBytes(3);
            Console.WriteLine(bytes);
        }

        static void Main(string[] args) {
            ObjectTransformer1 objectTransformer1 = new ObjectTransformer1();
            ObjectTransformer2 objectTransformer2 = new ObjectTransformer2();
            CoutStructureBytes(objectTransformer1);
            CoutStructureBytes(objectTransformer2);
        }
    }
}
// bastAbstractTemplates.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

template&lt;typename DerivedClass&gt;
class IObjectTransformer {
public:
    template&lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes);
    template&lt;typename TStructure&gt; std::vector&lt;unsigned char&gt; ToBytes(TStructure structure);
private:
    IObjectTransformer() = default;

    friend DerivedClass;
};

template &lt;typename DerivedClass&gt;
template &lt;typename TStructure&gt;
TStructure IObjectTransformer&lt;DerivedClass&gt;::ToStructure(std::vector&lt;unsigned char&gt; bytes) {
    return static_cast&lt;DerivedClass*&gt;(this)-&gt;ToStructure(bytes);
}

template &lt;typename DerivedClass&gt;
template &lt;typename TStructure&gt;
std::vector&lt;unsigned char&gt; IObjectTransformer&lt;DerivedClass&gt;::ToBytes(TStructure structure) {
    return static_cast&lt;DerivedClass*&gt;(this)-&gt;ToBytes(structure);
}

class ObjectTransformer1 : public IObjectTransformer&lt;ObjectTransformer1&gt; {
public:
    template &lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes) {
        unsigned char* bytePointer = &amp;bytes[0];
        TStructure structure = reinterpret_cast&lt;TStructure&gt;(*bytePointer);
        return structure;
    }

    template &lt;typename TStructure&gt; std::vector&lt;unsigned char&gt; ToBytes(TStructure structure) {
        char* bytesArray = reinterpret_cast&lt;char*&gt;(&amp;structure);
        auto byteVec = std::vector&lt;unsigned char&gt;(bytesArray, bytesArray + sizeof(TStructure));
        return byteVec;
    }
};

class ObjectTransformer2 : public IObjectTransformer&lt;ObjectTransformer2&gt; {
public:
    template &lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes) {
        TStructure structure{};
        std::memcpy(&amp;structure, &amp;bytes[0], sizeof(TStructure));
        return structure;
    }
    template &lt;typename TStructure&gt;
    std::vector&lt;unsigned char&gt; ToBytes(TStructure structure) {
        std::vector&lt;unsigned char&gt; bytes{};
        bytes.resize(sizeof(TStructure));
        std::memcpy(&amp;bytes[0], &amp;structure, sizeof(TStructure));
        return bytes;
    }
};


template &lt;typename DerivedClass, typename TStructure&gt;
void CoutStructureBytes(IObjectTransformer&lt;DerivedClass&gt; *objectTransformerBaseAbstractClass, TStructure structure) {
    auto bytes = objectTransformerBaseAbstractClass-&gt;template ToBytes&lt;TStructure&gt;(structure);
    for(auto byte : bytes) {
        std::cout &lt;&lt; std::to_string(byte) &lt;&lt; ' ';
    }
    std::cout &lt;&lt; std::endl;
}

int main() {
    ObjectTransformer1 objectTransformer1{};
    ObjectTransformer1 objectTransformer2{};

    int integer = 5;
    float someFloat = 9.79f;

    CoutStructureBytes(&amp;objectTransformer1, integer);
    CoutStructureBytes(&amp;objectTransformer2, someFloat);
}
在C#中,它只适用于“哈哈C#接口、模板、多态性go brrr”风格。即使你对C语言不熟悉,但有C++知识,我相信你可以遵循C代码。 这可以很好地编译和运行,并抛出NotImplementedException,因为它没有实现

<>但是,在C++中,与C语言不同,我不能仅仅使用通常的工具与模板、继承和多态进行接口:纯抽象函数(在派生类中重写)、模板、继承和方法重写。因为我不能将方法模板与虚拟模板混合使用

经过几天的研究,我终于发现了这一点: [^]

CRTP和静态多态性。最后,C++版本的我试图实现的行为:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace baseAbstractTemplates.NET {
    interface IObjectTransformer {
        TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes);
        ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure);
    };

    class ObjectTransformer1 : IObjectTransformer {

        #region Implementation of IObjectTransformerBaseAbstractClass

        public TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes) {
            throw new NotImplementedException();
        }

        public ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure) {
            throw new NotImplementedException();
        }

        #endregion

    }

    class ObjectTransformer2 : IObjectTransformer {

        #region Implementation of IObjectTransformerBaseAbstractClass

        public TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes) {
            throw new NotImplementedException();
        }

        public ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure) {
            throw new NotImplementedException();
        }

        #endregion

    }

    class Program {
        public static void CoutStructureBytes(IObjectTransformer objectTransformer) {
            var bytes = objectTransformer.ToBytes(3);
            Console.WriteLine(bytes);
        }

        static void Main(string[] args) {
            ObjectTransformer1 objectTransformer1 = new ObjectTransformer1();
            ObjectTransformer2 objectTransformer2 = new ObjectTransformer2();
            CoutStructureBytes(objectTransformer1);
            CoutStructureBytes(objectTransformer2);
        }
    }
}
// bastAbstractTemplates.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

template&lt;typename DerivedClass&gt;
class IObjectTransformer {
public:
    template&lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes);
    template&lt;typename TStructure&gt; std::vector&lt;unsigned char&gt; ToBytes(TStructure structure);
private:
    IObjectTransformer() = default;

    friend DerivedClass;
};

template &lt;typename DerivedClass&gt;
template &lt;typename TStructure&gt;
TStructure IObjectTransformer&lt;DerivedClass&gt;::ToStructure(std::vector&lt;unsigned char&gt; bytes) {
    return static_cast&lt;DerivedClass*&gt;(this)-&gt;ToStructure(bytes);
}

template &lt;typename DerivedClass&gt;
template &lt;typename TStructure&gt;
std::vector&lt;unsigned char&gt; IObjectTransformer&lt;DerivedClass&gt;::ToBytes(TStructure structure) {
    return static_cast&lt;DerivedClass*&gt;(this)-&gt;ToBytes(structure);
}

class ObjectTransformer1 : public IObjectTransformer&lt;ObjectTransformer1&gt; {
public:
    template &lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes) {
        unsigned char* bytePointer = &amp;bytes[0];
        TStructure structure = reinterpret_cast&lt;TStructure&gt;(*bytePointer);
        return structure;
    }

    template &lt;typename TStructure&gt; std::vector&lt;unsigned char&gt; ToBytes(TStructure structure) {
        char* bytesArray = reinterpret_cast&lt;char*&gt;(&amp;structure);
        auto byteVec = std::vector&lt;unsigned char&gt;(bytesArray, bytesArray + sizeof(TStructure));
        return byteVec;
    }
};

class ObjectTransformer2 : public IObjectTransformer&lt;ObjectTransformer2&gt; {
public:
    template &lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes) {
        TStructure structure{};
        std::memcpy(&amp;structure, &amp;bytes[0], sizeof(TStructure));
        return structure;
    }
    template &lt;typename TStructure&gt;
    std::vector&lt;unsigned char&gt; ToBytes(TStructure structure) {
        std::vector&lt;unsigned char&gt; bytes{};
        bytes.resize(sizeof(TStructure));
        std::memcpy(&amp;bytes[0], &amp;structure, sizeof(TStructure));
        return bytes;
    }
};


template &lt;typename DerivedClass, typename TStructure&gt;
void CoutStructureBytes(IObjectTransformer&lt;DerivedClass&gt; *objectTransformerBaseAbstractClass, TStructure structure) {
    auto bytes = objectTransformerBaseAbstractClass-&gt;template ToBytes&lt;TStructure&gt;(structure);
    for(auto byte : bytes) {
        std::cout &lt;&lt; std::to_string(byte) &lt;&lt; ' ';
    }
    std::cout &lt;&lt; std::endl;
}

int main() {
    ObjectTransformer1 objectTransformer1{};
    ObjectTransformer1 objectTransformer2{};

    int integer = 5;
    float someFloat = 9.79f;

    CoutStructureBytes(&amp;objectTransformer1, integer);
    CoutStructureBytes(&amp;objectTransformer2, someFloat);
}

“接受不同类型的参数”vs“而不使用模板”。???提示:请将代码简化为一个仅显示问题所在的示例。示例方法中的所有内容实际上只是在浪费读者的时间。一个简单的打印就足够了!请删除所有memcpy/resize,bla的东西,因为它实际上与具有未知参数类型的抽象基类无关…@Klaus好的,我将示例简化为只包含基类和派生类,不包含实现。我理解不可能同时使用模板和虚函数。这就是我试图解决问题的方法,但失败了。我确信我的问题有一个解决方案,也有可能解决我的问题,但在这种情况下,我不能同时使用模板和虚拟函数。我更仔细地了解了您试图实现的目标,并编辑了我的答案,以得出一个可能的解决方案。感谢您不厌其烦地编写此示例。不过,我的序列化示例只是一个示例。我在使用模板化方法实现多态性和继承以减少代码重复之后,序列化示例只是一个示例。请看我的答案:stackoverflow.com/a/62802439/6693304我自己写了这段代码,但我想我会习惯的。
static TypedStructureBuilder<SomeStructure> builder;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace baseAbstractTemplates.NET {
    interface IObjectTransformer {
        TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes);
        ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure);
    };

    class ObjectTransformer1 : IObjectTransformer {

        #region Implementation of IObjectTransformerBaseAbstractClass

        public TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes) {
            throw new NotImplementedException();
        }

        public ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure) {
            throw new NotImplementedException();
        }

        #endregion

    }

    class ObjectTransformer2 : IObjectTransformer {

        #region Implementation of IObjectTransformerBaseAbstractClass

        public TStructure ToStructure&lt;TStructure&gt;(ICollection&lt;byte&gt; bytes) {
            throw new NotImplementedException();
        }

        public ICollection&lt;byte&gt; ToBytes&lt;TStructure&gt;(TStructure structure) {
            throw new NotImplementedException();
        }

        #endregion

    }

    class Program {
        public static void CoutStructureBytes(IObjectTransformer objectTransformer) {
            var bytes = objectTransformer.ToBytes(3);
            Console.WriteLine(bytes);
        }

        static void Main(string[] args) {
            ObjectTransformer1 objectTransformer1 = new ObjectTransformer1();
            ObjectTransformer2 objectTransformer2 = new ObjectTransformer2();
            CoutStructureBytes(objectTransformer1);
            CoutStructureBytes(objectTransformer2);
        }
    }
}
// bastAbstractTemplates.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

template&lt;typename DerivedClass&gt;
class IObjectTransformer {
public:
    template&lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes);
    template&lt;typename TStructure&gt; std::vector&lt;unsigned char&gt; ToBytes(TStructure structure);
private:
    IObjectTransformer() = default;

    friend DerivedClass;
};

template &lt;typename DerivedClass&gt;
template &lt;typename TStructure&gt;
TStructure IObjectTransformer&lt;DerivedClass&gt;::ToStructure(std::vector&lt;unsigned char&gt; bytes) {
    return static_cast&lt;DerivedClass*&gt;(this)-&gt;ToStructure(bytes);
}

template &lt;typename DerivedClass&gt;
template &lt;typename TStructure&gt;
std::vector&lt;unsigned char&gt; IObjectTransformer&lt;DerivedClass&gt;::ToBytes(TStructure structure) {
    return static_cast&lt;DerivedClass*&gt;(this)-&gt;ToBytes(structure);
}

class ObjectTransformer1 : public IObjectTransformer&lt;ObjectTransformer1&gt; {
public:
    template &lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes) {
        unsigned char* bytePointer = &amp;bytes[0];
        TStructure structure = reinterpret_cast&lt;TStructure&gt;(*bytePointer);
        return structure;
    }

    template &lt;typename TStructure&gt; std::vector&lt;unsigned char&gt; ToBytes(TStructure structure) {
        char* bytesArray = reinterpret_cast&lt;char*&gt;(&amp;structure);
        auto byteVec = std::vector&lt;unsigned char&gt;(bytesArray, bytesArray + sizeof(TStructure));
        return byteVec;
    }
};

class ObjectTransformer2 : public IObjectTransformer&lt;ObjectTransformer2&gt; {
public:
    template &lt;typename TStructure&gt; TStructure ToStructure(std::vector&lt;unsigned char&gt; bytes) {
        TStructure structure{};
        std::memcpy(&amp;structure, &amp;bytes[0], sizeof(TStructure));
        return structure;
    }
    template &lt;typename TStructure&gt;
    std::vector&lt;unsigned char&gt; ToBytes(TStructure structure) {
        std::vector&lt;unsigned char&gt; bytes{};
        bytes.resize(sizeof(TStructure));
        std::memcpy(&amp;bytes[0], &amp;structure, sizeof(TStructure));
        return bytes;
    }
};


template &lt;typename DerivedClass, typename TStructure&gt;
void CoutStructureBytes(IObjectTransformer&lt;DerivedClass&gt; *objectTransformerBaseAbstractClass, TStructure structure) {
    auto bytes = objectTransformerBaseAbstractClass-&gt;template ToBytes&lt;TStructure&gt;(structure);
    for(auto byte : bytes) {
        std::cout &lt;&lt; std::to_string(byte) &lt;&lt; ' ';
    }
    std::cout &lt;&lt; std::endl;
}

int main() {
    ObjectTransformer1 objectTransformer1{};
    ObjectTransformer1 objectTransformer2{};

    int integer = 5;
    float someFloat = 9.79f;

    CoutStructureBytes(&amp;objectTransformer1, integer);
    CoutStructureBytes(&amp;objectTransformer2, someFloat);
}