C ++:通用基本成员函数,在派生类中具有特定类型

时间:2014-07-28 21:53:44

标签: c++ inheritance

很快就会明白,我还在学习C ++ 对于我正在处理的问题,我有一个类,它有一个std :: map数据成员和一些在地图上运行的成员函数。我将需要一些实例,其中地图按升序排序,而一些实例的地图按降序排序。对于这两种情况,成员函数的代码都是相同的(除了类型问题 - 正如我所知,更改映射的比较函数会改变其类型)。我正在努力完成这项工作,而不必为每个案例重写功能。

这里有一些玩具代码,我希望能说明我的情况(内联功能只是为了紧凑):

class MyClass {
public:
    map<int, int>::iterator get_top(){ return data.begin(); }
    int sum_elements(){ 
        int sum = 0;
        for ( map<int,int>::iterator it = data.begin(); it != data.end(); ++it){
            sum += it->second;
        }
    }
};

理想情况下,我会有一个定义函数的基类和两个定义数据成员的派生类,一个用于升序,一个用于降序:

class Ascending : public MyClass {
private:
    std::map<int, int, std::less<int> > data;
};
class Descending : public MyClass {
private:
    std::map<int, int, std::greater<int> > data;
};

但是当然这不起作用,因为基类需要定义数据成员才能对其进行操作。 “简单”的出路是拥有两个独立的类,并将成员函数复制/粘贴到两者中。但这会浪费,我觉得C ++必须有一个优雅的解决方案来解决我的问题。

1 个答案:

答案 0 :(得分:1)

定义一个重载operator()(int, int)(比较)的仿函数,并将构造函数作为对元素进行排序的顺序。这样,您就可以定义地图 作为std::map<int, int, SortCriterion> data(comp),其中comp定义为SortCriterion comp(true),例如升序,SortCriterion comp(false)定义为降序。这样,两个地图都将具有相同的类型map<int, int, SortingCriterion>

以下代码:

#include <map>
#include <iostream>

using namespace std;

class SortCriterion
{
    bool ascending;
public:
    SortCriterion(bool sorting_type): ascending(sorting_type){};
    bool operator()(int x, int y) const
    // if not marked const, 
    // clang++ spits a compile-time error on insert
    // however g++ compiles it ok
    {
        if(ascending) // ascending
            return x<y;
        else
            return x>y;
    }
};

int main()
{
    // Both maps below have the SAME type, map<int, int, SortCriterion>
    map<int, int, SortCriterion> m1(SortCriterion(true)); // ascending
    map<int, int, SortCriterion> m2(SortCriterion(false)); // descending


    m1.insert({1,1});
    m1.insert({2,2});

    m2.insert({1,1});
    m2.insert({2,2});

    cout << "First map:" << endl;
    for(auto elem: m1)
        cout << "[" << elem.first << "," << elem.second\
             << "]" << endl;

    cout << endl << "Second map:" << endl;
    for(auto elem: m2)
        cout << "[" << elem.first << "," << elem.second\
             << "]" << endl;
}