c ++运算符重载参数与普通参数

时间:2013-05-07 12:16:08

标签: c++ templates implicit-conversion overloading overload-resolution

我有一个功能模板(c ++)

template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")

重载功能

template<typename T>
void print_to_default_file(T &obj, std::string  objS) // or char* objS

ADDON具有以下签名的运算符重载

void operator=(const std::string)

问题是,当我这样做时     print_to_default_file(“test”,“我将去哪里”)

正在调用第一个,但我想调用第二个。我也厌倦了char *而不是std :: string但结果是一样的。

任何人都可以指出出了什么问题

ADDON简化版

class ADDON {
    std::string s;

public:
    ADDON() {
        s = "";
    }

ADDON(std::string in) {
    s = in;
}

    ADDON(const char in[]) {
        s = in;
    }

    void operator=(const std::string in) {
        s = in;
    }

    std::string getString() {
        return s;
    }
};

1 个答案:

答案 0 :(得分:5)

您的原始代码无法编译

您向我们展示的代码

#include <iostream>
#include <string>

class ADDON {
    std::string s;

public:
    ADDON() {
        s = "";
    }

    ADDON(std::string in) {
        s = in;
    }

    ADDON(const char in[]) {
        s = in;
    }

    void operator=(const std::string in) {
        s = in;
    }

    std::string getString() {
        return s;
    }
};

template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")
{ std::cout << "first overload\n"; }

template<typename T>
void print_to_default_file(T &obj, std::string  objS) 
{ std::cout << "second overload\n"; }

int main()
{
     print_to_default_file("test","where will I go");
}

无法编译(online output)并出现以下错误

  

prog.cpp:在函数'int main()'中:prog.cpp:39:52:错误:调用   重载'print_to_default_file(const char [5],const char [16])'是   模棱两可的prog.cpp:39:52:注意:候选人是:prog.cpp:30:6:注意:   void print_to_default_file(T&amp;,ADDON)[with T = const char [5]]   prog.cpp:34:6:注意:void print_to_default_file(T&amp;,std :: string)[with   T = const char [5]; std :: string = std :: basic_string]

原因是名称查找和参数推断找到2个候选者:第一个重载需要const char*ADDON转换,第二个重载需要const char*std::string转换。两个转换序列都是同样好的匹配,过载资源不明确,程序也不正确。

一个简单的修复

只需更改第二个重载,将const char*作为参数(而不是char*,它不能绑定字符串文字),它将是原始字符串文字作为参数的最佳匹配

template<typename T>
void print_to_default_file(T &obj, const char*  objS) // but NOT char* objS
{ std::cout << "second overload\n"; }

您现在将获得第二次重载(online output)。要选择第一个重载,只需在参数列表中调用ADDON构造函数

int main()
{
     print_to_default_file("test", ADDON("where will I go"));
}

请注意,这将调用ADDON(const char[])构造函数而不是ADDON(std::string)构造函数,因为后者需要用户定义的转换(online output)。

正确修复

拥有非显式的单个参数构造函数是非常危险的。始终在这些功能周围使用explicit关键字。

class ADDON {
    std::string s;

public:
    ADDON() {
        s = "";
    }

    explicit ADDON(std::string in) {
        s = in;
    }

    explicit ADDON(const char in[]) {
        s = in;
    }

    void operator=(const std::string in) {
        s = in;
    }

    std::string getString() {
        return s;
    }
};

这也会调用第二个重载(online output),因为ADDON重载没有显式调用任何构造函数。要选择第一个重载,请再次调用参数列表中的ADDON构造函数。