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

标签 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("测试","我要去哪里")

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

最佳答案

您的原始代码无法编译

您向我们展示的代码

#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: In function ‘int main()’: prog.cpp:39:52: error: call of overloaded ‘print_to_default_file(const char [5], const char [16])’ is ambiguous prog.cpp:39:52: note: candidates are: prog.cpp:30:6: note: void print_to_default_file(T&, ADDON) [with T = const char [5]] prog.cpp:34:6: note: 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* 作为参数(而不是作为 char*,它无法与字符串文字绑定(bind)),这将是最好的匹配原始字符串文字作为参数

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 构造函数。

关于C++ 运算符重载参数与普通参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16418821/

相关文章:

c++ - 使用散列查找数组中一个重复的数字和一个缺失的数字

c++ - 将 std::get 与枚举类一起使用时需要 static_cast

C++14 对 is_same::value 使用别名

c++ - 为什么 bool(val) 比 val.operator bool() 更喜欢双重隐式转换?

c - C11 标准编译器接受的替代函数指针语法

c++ - 确定两个字符串是否因相邻字符交换而不同的最快方法? C++

Qt 库推荐使用 C++ Qt Creator 版本 4.8.5

c++ - 在最简单的赋值中打破严格的别名规则

c++ - 使用模板和可变参数模板进行线程初始化

c# - 如果隐式已在 C# 中重载,则重载显式运算符是否有好处?