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

sim*_*ser 2 c++ templates overloading overload-resolution implicit-conversion

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

template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")
Run Code Online (Sandbox Code Playgroud)

和一个重载的功能

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

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

void operator=(const std::string)
Run Code Online (Sandbox Code Playgroud)

问题是,当我执行print_to_default_file("测试","我将去哪里")

它正在呼叫第一个,但我想打电话给第二个.我也厌倦了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;
    }
};
Run Code Online (Sandbox Code Playgroud)

Tem*_*Rex 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");
}
Run Code Online (Sandbox Code Playgroud)

不编译(在线输出),出现以下错误

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&,ADDON)[with T = const char [5]] prog.cpp:34:6:注意:void print_to_default_file(T&,std :: string)[with T = const char [5]; std :: string = std :: basic_string]

其原因是,名称查找和参数推导发现2名候选人:第一过载要求const char*,以ADDON转换,第二个过载const char*std::string转换.两个转换序列都是同样好的匹配,并且过载资源不明确且您的程序格式错误.

一个简单的修复

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

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

您现在将获得第二次重载(在线输出).要选择第一个重载,只需ADDON在参数列表中调用构造函数即可

int main()
{
     print_to_default_file("test", ADDON("where will I go"));
}
Run Code Online (Sandbox Code Playgroud)

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

正确的解决方案

拥有非显式的单个参数构造函数是非常危险的.始终使用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;
    }
};
Run Code Online (Sandbox Code Playgroud)

这也将调用第二个重载(在线输出),因为ADDON重载不会显式调用任何构造函数.要选择第一个重载,请再次ADDON在参数列表中调用构造函数.