从类外部重载成员函数

时间:2014-02-05 03:10:04

标签: c++ boost struct overloading

我正在编写文件处理系统(使用boost的属性树)。我正在努力使其易于使用和扩展,因为为每个新项目开发文件系统始终是一个重要的时间。

我大部分时间都在工作。我可以调用add_data(“meta.timeinfo”,“date”,“10/12/13”)将10/12/13添加到嵌套在元节点中的timeinfo节点下的日期键。我还可以调用add_data(“meta.timeinfo”,“date”,date_created)将该相同变量的值写入字符串。我已经确定它会对所有非向量进行相同处理,并且所有向量都相同。

当我想扩展它以使用结构时,我的问题就来了。我想从struct的文件中过载add_data和get_data函数(我将把基本系统编译为库。)当重载opperator时,你通常只做这样的事情:

    void LBUtil::data_holder::add_data(std::string section, std::string key, tile_template data)
{
    if(section != "") section += ".";
    std::string sectionKey = section+key+".";

    propertyTree.put(sectionKey+"ID", data.ID);

    propertyTree.put(sectionKey+"xPos", data.xPos);
    propertyTree.put(sectionKey+"yPos", data.yPos);

    propertyTree.put(sectionKey+"height", data.height);
    propertyTree.put(sectionKey+"width", data.width);

    propertyTree.put(sectionKey+"depth", data.depth);

    propertyTree.put(sectionKey+"friction", data.friction);
    propertyTree.put(sectionKey+"water", data.water);
};

但是当我尝试这样做时,我收到以下错误:

  

错误C2511:'无效   LBUtil :: data_holder :: add_data工具(的std :: string,的std :: string,tile_template)”   :'LBUtil :: data_holder'中找不到重载的成员函数

如果它有帮助,我的data_holder类代码如下

#ifndef _LBUTIL_FILESYSTEM_DATA_HOLDER_H
#define _LBUTIL_FILESYSTEM_DATA_HOLDER_H

#include <string>
#include <vector>

#include <boost/property_tree/ptree.hpp>
#include <boost/lexical_cast.hpp>

namespace LBUtil
{
    class data_holder
    {
        friend class file_holder;

    public:
        template<typename DATA_TYPE>
        void add_data(std::string section, std::string key, DATA_TYPE data)
        {
            if(section != "") section += ".";
            propertyTree.put(section + key, data);
        };

        template<typename DATA_TYPE>
        void add_data(std::string section, std::string key, std::vector<DATA_TYPE> data)
        {
            if(section != "") section += ".";

            std::string sectionKey = section + key+".";
            remove_data(section,key);

            propertyTree.put(sectionKey+"count", data.size());

            for(unsigned int i = 0; i < data.size(); i++) {
                propertyTree.put(sectionKey+boost::lexical_cast<std::string>(i), data[i]);
            }
        };

        template<typename DATA_TYPE>
        void get_data(std::string section, std::string key, DATA_TYPE &data)
        {
            get_key(section,key,data);
        };

        template<typename DATA_TYPE>
        void get_data(std::string section, std::string key, std::vector<DATA_TYPE> &data)
        {
            if(section != "") section += ".";
            data.clear();

            unsigned int count = -1;
            std::string sectionKey = section + key+".";

            get_key(section+key,"count",count);

            if(count == -1) return;

            for(unsigned int i = 0; i < count; i++) {
                DATA_TYPE element = propertyTree.get<DATA_TYPE>(sectionKey+boost::lexical_cast<std::string>(i));
                data.push_back(element);
            }
        };

        void data_holder::remove_data(std::string parent, std::string target)
        {
            if(target != "") propertyTree.get_child(parent).erase(target);
            else propertyTree.erase(parent);
        }

    protected:
        template<typename DATA_TYPE>
        void get_key(std::string section, std::string key, DATA_TYPE& data)
        {
            if(section != "") section += ".";

            boost::optional<DATA_TYPE> value = propertyTree.get_optional<DATA_TYPE>(section+key);

            if(value) data = value.get();
        };

        boost::property_tree::ptree propertyTree;


    };
}

#endif

我试图扩展data_holder类的结构如下:

#ifndef _LBMOON_TEST_TILE_TEMPLATE_H
#define _LBMOON_TEST_TILE_TEMPLATE_H

struct tile_template
{
    int ID;

    int xPos;
    int yPos;

    int height;
    int width;

    int depth;

    float friction;
    bool water;
};

void LBUtil::data_holder::add_data(std::string section, std::string key, tile_template data)
{
    if(section != "") section += ".";
    std::string sectionKey = section+key+".";

    propertyTree.put(sectionKey+"ID", data.ID);

    propertyTree.put(sectionKey+"xPos", data.xPos);
    propertyTree.put(sectionKey+"yPos", data.yPos);

    propertyTree.put(sectionKey+"height", data.height);
    propertyTree.put(sectionKey+"width", data.width);

    propertyTree.put(sectionKey+"depth", data.depth);

    propertyTree.put(sectionKey+"friction", data.friction);
    propertyTree.put(sectionKey+"water", data.water);
};

#endif

有没有办法可以避免在我定义add_data和get_data函数的所有新版本的每个项目中处理创建子类的问题?

1 个答案:

答案 0 :(得分:0)

看起来你已经在类中创建了一个没有函数声明的函数定义。这是一个问题,可能是给你编译错误的问题。您必须在类定义中包含一个函数声明才能使其生效。但我认为这不是你的意图。

在C ++中,您可以使用模板有效地“重载”数据类型,但是完全替换函数体的唯一方法是创建另一个派生它的类并替换该函数。 (经营者很特别。)

所以你可以这样做:

   data_holder mMyDataHolder;
    tile_template data;
    data_holder.add_data(section, key, data);

将传递你的新结构。但它不会改变行为。

我认为最适合您总体目标的是让您的整个课程模板化。这样你就可以将想要重载的函数声明为虚拟,如下所示:

template <class DataType>
class MyClass
{
public:
  virtual int OverloadThis( DataType &dt)
  {
    return 0;
  }
};
//You can overload it like this:
class MyDerivedClass : public MyClass<int>
{
public:
  virtual int OverloadThis( int &dt )
  {
    return 1;
  }
};
//Or like this:
template <class DataType>
class MyDerivedClass2 : public MyClass<DataType>
{
public:
  virtual int OverloadThis( DataType &dt )
  {
    return 2;
  }
};

从技术上讲,该功能不一定是虚拟的。它仍然会重载BUT对它的引用从基类中调用基类的函数实例而不是派生类的函数实例。 (如果你已经习惯了java,你会想要使用虚拟。你会更熟悉继承如何工作。)