隐式调用复制构造函数

5

请考虑:

struct Foo
{
    Foo(std::string str) {}
};

struct Bar
{
    Bar(Foo f) {}
};

int main(int argc, char* argv[])
{
    Foo f("test");

    Bar b1(f);
    Bar b2(std::string("test"));
    Bar b3("test");

    return 0;
}

在b3声明时会编译失败('不能将参数1从 'const char [5]' 转换为 'Foo''),这是有道理的,因为没有直接将const char转换为Foo的方法。然而,有一种方式可以将const char转换为std::string,然后使用它来构造一个Foo(这就是b1和b2中发生的情况),这正是我想要的,因为它使API更易于使用(不需要每次都显式实例化Foo或std::string)。

所以我的问题是:是否有办法让编译器隐式调用Foo(std::string)复制构造函数?换句话说,是否有一种让像b3那样的声明工作的方法,让它与b2相同,并且不需要为Foo声明const char*复制构造函数?(最后一件事是显然的,但我的真实代码当然不像这么简单,而且我宁愿不添加const char *复制构造函数,并正确处理所有其他初始化,保持它们与std::string复制构造函数的同步)。


6
一个隐式转换序列只允许包含一个用户定义的转换。你正在请求两个(从const char*std::string,然后从std::stringFoo)。解决方法之一是添加一个以const char*为参数的Foo构造函数重载。 - Igor Tandetnik
吹毛求疵:您提到的所有构造函数都不是“拷贝”构造函数,它们只是构造函数。 - molbdnilo
谢谢,'隐式转换序列'是我正在寻找的魔术字符串。事实上,我想做的是不可能的,我将不得不使用额外的构造函数。 - Roel
回复:挑剔一下,是的,似乎标准并不称那些被视为复制初始化的构造函数为“复制构造函数”。我自己一直这样做,从这个问题中学到了两件事 :) - Roel
2个回答

8
如果可以使用C++11,你可以在Foo中添加一个委托构造函数,它接受一个const char*并调用其他构造函数:
struct Foo
{
    Foo(std::string str) {}
    Foo(const char* str) : Foo(std::string(str)) {}
};

或者,您可以使用c++14的std::string字面值:

using namespace::std::string_literals;
Bar b3("test"s);

您也可以通过让两个构造函数调用一个单独的函数来模拟委托构造函数:
struct Foo
{
    Foo(std::string str) { init(str); }
    Foo(const char* str) { init(str); }
    void init(std::string str) {}
};

以上方法的缺点是,您需要仔细考虑在初始化列表中所做的任何事情,现在都需要在init的主体中完成。

VS2013,没有委托构造函数和std :: string字面值 :( - Roel
@Roel,你觉得模拟委托构造函数怎么样?就像我编辑中的那样。 - TartanLlama
1
是的,我想那就是我最终要做的。缺点(我相信你也知道)是成员不会在原地构造。从速度上来说,在我的代码中几乎不会有任何可感知或可测量的影响,但仍然感觉有点不舒服 ;) - Roel
1
@Roel:VS2013具有委托构造函数,如此处所示:https://msdn.microsoft.com/zh-cn/library/hh567368.aspx - Rosme
它使用委托构造函数在VC++2013中在线编译。 - SChepurin
哦,我之前在 https://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx 上看到它不支持这个功能,但可能是我看错了。谢谢! - Roel

1

怎么样改变这个:

struct Bar
{
    Bar(Foo f) {}
};

struct Bar
{
    Bar(Foo f) {}
    Bar(std::string f) {}
};

使用多态...

5
通常意义上的面向对象编程中的多态性与此无关,这仅仅是重载。 - Puppy
谢谢,但在我的情况下,这会遭受与我试图通过不使用const char*构造函数来避免的相同维护问题。看来我需要再创建一个构造函数才能使其工作。 - Roel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接