【问题标题】:Function overload with same parameter type in C++C++中具有相同参数类型的函数重载
【发布时间】:2012-06-05 12:29:26
【问题描述】:

我想重写一个参数类型相同但逻辑含义不同的函数。我尝试过类似的方法:

class T
{
};

typedef T Age;
typedef T Height;
typedef T Weight;

void foo(Age a){}
void foo(Height a){}
void foo(Weight a){}

但我有构建错误: 错误 C2084:函数 'void foo(Age)' 已经有一个主体

一种解决方案是:

class Age : public T{};
class Height : public T{};
class Weight : public T{};

但我不想仅仅为此目的用新类填充我的命名空间。

如何在不使用派生类的情况下实现这一点?

编辑:我的代码在一个 cpp 文件中,我不使用标题。这只是一个简单的例子。完整的 cpp 内容在这里:

class T
{
};

typedef T Age;
typedef T Height;
typedef T Weight;

void foo(Age a){}
void foo(Height a){}
void foo(Weight a){}

int main()
{
    return 0;
}

错误信息: .cpp(10): error C2084: function 'void foo(Age)' already has a body

【问题讨论】:

  • typedef 创建 T 的别名。即使这样也填满了命名空间
  • 如果你想要新的类型,你只需必须声明新的类型。 typedef 只是为同一类型创建一个新的 name。假设Tint - 编译器将如何解析foo(42)
  • @BoPersson 我永远不会使用直接值调用函数。这些函数是序列化类的一部分,我需要以不同的方式进行序列化,具体取决于文件类型、Path 对象
  • @Felics - 没有区别。在这种情况下,typedef T Age; 只是#define Age T 的作用域版本。 typedef 不会创建新类型,因此不能用于重载。

标签: c++


【解决方案1】:

试试BOOST_STRONG_TYPEDEF,它是Boost.Serialization中的avalailabel。

【讨论】:

  • 这将使用宏来用新类填充命名空间。 :-)
【解决方案2】:

您可以将模板用作:

//1. First define T as class template
template<typename U>
class T
{
 public:
    typedef U tag_type;  //you may need this to inspect the type
    //...
};

//2. then define some tags
struct tag_age{};
struct tag_height{};
struct tag_weight{};

//3. then define typedefs
typedef T<tag_age> Age;
typedef T<tag_height> Height;
typedef T<tag_weight> Weight;

//4. then function overloads
void foo(Age a){}
void foo(Height a){}
void foo(Weight a){}

这样,每个typedef都是不同的类型,并且不能隐式转换成其他类型,除非你在类的定义中明确允许这个功能模板T.

【讨论】:

    【解决方案3】:

    我认为这不是 typedef 的适当用法 - 至少就您的示例而言,这可能在生产代码中有所不同。但是,恕我直言,这不是 typedef 应该使用的。你应该正确命名你的变量和函数,因为它们会做不同的逻辑事情:

    void doAge(T age);
    void doHeight(T height);
    

    更新:那么 typedef 在哪里合适呢?

    在您的情况下,该解决方案会使代码复杂化,因此它似乎相当不合适。应该使用 Typedef 来简化事情。例如,请参阅我对以下问题的回答:Meaning of complex C syntax

    【讨论】:

    • +1 for 这不是 typedef 应该用于的。这个最简单和最直观的解决方案。
    【解决方案4】:

    你基本上是在错误的轨道上。更改实际参数的名称而不是其类型。你在做什么没有意义。 typedef 基本上使用二级简化名称来更多地与手头的代码相关,但它只是程序员的简写,编译器在所有情况下仍然会看到 T。

    一个数字可能代表年龄、球数、长度、身高……在所有情况下,它们的逻辑用途是不同的,但用于对其信息进行编码的基本数据类型保持不变。你不应该这样接近它。

    【讨论】:

      【解决方案5】:

      你可以使用标签来做到这一点

      class T{};
      
      typedef T Age;
      typedef T Height;
      typedef T Weight;
      
      struct age_tag {};
      struct height_tag {};
      struct weight_tag {};
      
      void foo(Age a, age_tag ){...}
      void foo(Height h, height_tag ){...}
      void foo(Weight a, weight_tag ){...}
      
      template<typename TAG> void bar(T t);
      template<> void bar<age_tag>(Age a) {...};
      template<> void bar<height_tag>(Height h) {...};
      template<> void bar<weight_tag>(Weight a) {...};
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        • 1970-01-01
        • 2015-04-25
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多