通用抽象类型c ++

时间:2012-01-24 14:09:18

标签: c++ generics generic-programming generic-type-argument

我想在c ++中定义一个允许在任何数据上执行算法的泛型类。问题是这个数据可以是任何东西(例如浮点数,图形等)。是否有可能在我的班级中说操纵数据是T类型可以是什么?然后我班级的用户将不得不实施我的班级相对于操纵他的数据的一些方法(例如,根据他的数据,他定义如何做两个数据的总和等等)。

编辑:

如何实例化类模板并调用其方法?我这样做时出错:

MyClass<int, int> tst();
tst.test(3, 4); // or even with tst.test<int, int>(3, 4);

错误:在'tst'中请求成员'test',这是非类型'MyClass()'

该类如果定义为:

#include <iostream>
#include <boost/graph/adjacency_list.hpp>

using namespace std;
using namespace boost;

template<typename T1, typename T2>
class MyClass
{
    public:
        MyClass();
        virtual ~MyClass();
        void test(T1 p, T2 s);

    protected:
        struct NodeData
        {
            T1 var1;
            T2 var2;
            int var3;
        };

        struct EdgeData
        {
            int var;
        };

        typedef adjacency_list<setS, setS, undirectedS, NodeData, EdgeData> Graph;
        typedef typename Graph::vertex_descriptor NodeDataID;
        typedef typename Graph::edge_descriptor EdgeDataID;
        typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;

        Graph g;
};

template<typename T1, typename T2>
void MyClass<T1, T2>::test(T1 arg1, T2 arg2)
{
    NodeDataID nId = add_vertex(g);
    g[nId].anything = "but anything is not in struct NodeData !";
    g[nId].var1 = arg1;
    g[nId].var2 = arg2;
    g[nId].var3 = 55;
}

template<typename T1, typename T2>
MyClass<T1, T2>::MyClass()
{
    // ...
}

template<typename T1, typename T2>
MyClass<T1, T2>::~MyClass()
{
    // ...
}

4 个答案:

答案 0 :(得分:2)

是的,您可以这样做,只要您希望在班级中使用的所有不同类型的数据都支持您的算法所需的操作。

如果您将模板方法用于所需的特定于类型的操作,那么您的用户可以将这些方法专门用于需要非默认实现的输入类。

答案 1 :(得分:2)

正如@Als评论,你完美地描述了一个类模板

您可以在http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fclass_templates.htm

了解相关主题

答案 2 :(得分:1)

假设<T>必须保持一致:

我建议有一个接受“操作处理程序”的类。传入的操作处理程序将处理所有类型特定的操作。这是一个令人难以置信的粗略示例,我甚至不确定它的功能是什么,因为我在一段时间内没有实现它并且编写c ++而没有编译器纯粹来自内存。也就是说,这应该表明基本的想法。

class CGenericOperationHandler<T>{

   public:
   Sum(<T> left,<T> right);

   Subtract(<T> left,<T> right);

   Multiply(<T> left,<T> right);

}

class CFloatOperationHandler : CGenericOperationHandler<float>{

   public:
   Sum(float left,float right){ return left + right; }

   Subtract(float left,float right){ return left - right; }

   Multiply(float left,float right){ return left * right; }

}


class CAlgoRunner<T>{

    CGenericOperationHandler<T>* myOpHandler;

    CAlgoRunner(CGenericOperationHandler<T>* opHandler){
        myOpHandler = opHandler;
    }

    public:
    <T> RunAlgo(<T> left, <T> right){
        return myOpHandler.Multiply(left, right);
    }

}


main(){
    CFloatOperationHandler theOpHandler;

    CAlgoRunner<float>* myRunner = new CAlgoRunner<float>( theOpHandler );

    float result = myRunner.RunAlgo( 6.0f, 1.5f); //result is (6 * 1.5) i.e. 9
}

答案 3 :(得分:0)

只有在一个文件(例如.cpp)中写入时才有效。如果您正在处理具有多个文件(标题和源)的大项目,则必须避免使用模板,因为编译器可以在使用模板时查看和分析模板。这是一个很大的问题,因为重新定义模板通常是错误的。