2

我有一个函数模板(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","where will I go")

它正在调用第一个,但我想调用第二个。我也厌倦了 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;
    }
};
4

1 回答 1

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");
}

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

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*toADDON转换,第二个重载需要一个const char*tostd::string转换。两种转换序列都是同样好的匹配,并且重载解决方案不明确,并且您的程序格式错误。

一个简单的修复

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

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

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

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

请注意,这将调用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;
    }
};

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

于 2013-05-07T12:21:05.677 回答