C++ 从类外部重载成员函数

C++ 从类外部重载成员函数,c++,boost,struct,overloading,C++,Boost,Struct,Overloading,我正在编写一个文件处理系统(使用boost的属性树)。我试图使它易于使用和扩展,因为为每个新项目开发一个文件系统总是一个大麻烦 大部分时间我都在工作。我可以调用add_data(“meta.timeinfo”、“date”、“10/12/13”)将10/12/13添加到meta节点中嵌套的timeinfo节点下的日期键中。我还可以调用add_data(“meta.timeinfo”、“date”、date_created”)将同一变量的值写入字符串。我已经设置好了,它会对所有的非向量,以及所有的

我正在编写一个文件处理系统(使用boost的属性树)。我试图使它易于使用和扩展,因为为每个新项目开发一个文件系统总是一个大麻烦

大部分时间我都在工作。我可以调用add_data(“meta.timeinfo”、“date”、“10/12/13”)将10/12/13添加到meta节点中嵌套的timeinfo节点下的日期键中。我还可以调用add_data(“meta.timeinfo”、“date”、date_created”)将同一变量的值写入字符串。我已经设置好了,它会对所有的非向量,以及所有的向量,一视同仁

当我想扩展它以使用结构时,我的问题就来了。我想从结构文件中加载add_data和get_data函数(我将把基本系统编译成一个库)。重载运算器时,通常只需执行以下操作:

    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_模板)' :在“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

在我定义所有新版本的add_data和get_data函数的每个项目中,是否有任何方法可以避免创建子类?

看起来您创建的函数定义中没有函数声明。这是一个问题,也可能是导致编译器错误的问题。您必须在类定义中包含一个函数声明,这样才能工作。但我不认为这是你的意图

在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;
  }
};
模板
类MyClass
{
公众:
虚拟int重载此(数据类型&dt)
{
返回0;
}
};
//您可以像这样重载它:
类MyDerivedClass:公共MyClass
{
公众:
虚拟int重载此(int&dt)
{
返回1;
}
};
//或者像这样:
样板
类MyDerivedClass2:公共MyClass
{
公众:
虚拟int重载此(数据类型&dt)
{
返回2;
}
};

从技术上讲,该功能不必是虚拟的。它仍将重载,但从基类中对它的引用将调用基类的函数实例,而不是派生类的函数实例。(如果你习惯java,你会想使用虚拟的。你会更熟悉继承的工作方式。)

你不能创建一个模板自由函数来替换
propertyTree.put(节+键,数据)
add_data
中,类似于
模板void-put(ptree-propertyTree,string-section,string-key,data-data){propertyTree.put(section+key,data);}
的东西,然后专门化为新类型?但这并不能改变问题。我不能从类外重载“put”函数。我希望能够将结构作为参数传递。因为在我将要使用的代码中,我将读取/写入充满结构的向量。因此,如果我可以从类外重载成员函数,这会使一切变得更简单。这就是为什么我说自由函数。使“put”成为一个自由函数,在classahok之外声明定义。我明白你的意思。如果没有其他解决方案,我会这么做。谢谢:)实际上,你甚至不需要免费的功能。您可以从类外部专门化
add_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;
  }
};