Foo f = Foo(); // 没有匹配的函数可用于调用“Foo::Foo(Foo)” ...嗯?

发布于 2024-09-01 03:51:09 字数 417 浏览 2 评论 0原文

class Foo
{
public:
    explicit Foo() {}
    explicit Foo(Foo&) {}
};

Foo d = Foo();

错误:没有调用“Foo::Foo(Foo)”的匹配函数

我尝试将 Foo(Foo&) 更改为 Foo(Foo) 正如错误所示,据我所知,这不是一个有效的构造函数,果然我得到:

错误:构造函数无效;你的意思可能是“Foo (const Foo&)”

什么给出了?我该如何解决这个问题? (顺便说一句,这是在 GCC 上)

class Foo
{
public:
    explicit Foo() {}
    explicit Foo(Foo&) {}
};

Foo d = Foo();

error: no matching function for call to 'Foo::Foo(Foo)'

I tried changing Foo(Foo&) to Foo(Foo) as the error suggests, which AFAIK is not a valid constructor, and sure enough I get:

error: invalid constructor; you probably meant ‘Foo (const Foo&)’

What gives? How do I resolve this? (This is on GCC by the way)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

过期以后 2024-09-08 03:51:09

复制构造函数中有两个有问题的东西。

首先,您已经使复制构造函数显式化(这是一件值得怀疑的事情),因此您(理论上)需要这样做:

Foo d( (Foo()) );

其次,您的复制构造函数采用引用而不是 const > 引用,这意味着您不能将其与临时 Foo 一起使用。

就我个人而言,我只是从复制构造函数中删除 explicit ,并在可能的情况下使其采用 const 引用。

请注意,默认构造函数上的 explicit 不起作用。[*] explicit 仅对可以使用单个参数调用的构造函数有效。它防止它们被用于隐式转换。对于仅采用零个或仅两个或更多参数的构造函数,它没有任何效果。

之间可能存在差异,

Foo d;

[注意::和

Foo d = Foo();

但在这种情况下,您有一个用户声明的默认构造函数,因此这不适用。]

编辑:
[*] 我刚刚仔细检查过这一点,12.3.1 [class.conv.ctor] 说你可以创建一个默认构造函数显式。在这种情况下,构造函数将用于执行默认初始化值初始化。老实说,我不明白 this 的值,因为如果你有一个用户声明的构造函数,那么它是一个非 POD 类型,甚至非 POD 类型的本地对象如果没有初始化程序,也会默认初始化该子句表示可以通过显式默认构造函数来完成。也许有人可以指出一个极端的情况,它确实会产生影响,但目前我还没有看到显式对默认构造函数有什么影响。

There are two questionable things that you have in your copy constructor.

First, you've made the copy-constructor explicit (which is a questionable thing to do), so you would (in theory) need to do:

Foo d( (Foo()) );

Second, your copy constructor takes a reference and not a const reference which means that you can't use it with a temporary Foo.

Personally, I'd just remove explicit from the copy-constructor and make it take a const reference if possible.

Note that the explicit on your default constructor has no effect.[*] explicit only has an effect on constructors that can be called with a single parameter. It prevents them being used for implicit conversions. For constructors that take only zero or only two or more parameters, it has no effect.

[Note: there can be a difference between:

Foo d;

and

Foo d = Foo();

but in this case you have a user-declared default constructor so this doesn't apply.]

Edit:
[*] I've just double checked this and 12.3.1 [class.conv.ctor] says that you can make a default constructor explicit. In this case the constructor will be used to perform default-initialization or value-initialization. To be honest, I don't understand the value of this as if you have a user-declared constructor then it's a non-POD type and even local objects of non-POD type are default-initialized if they don't have an initializer which this clause says can be done by an explicit default constructor. Perhaps someone can point out a corner case where it does make a difference but for now I don't see what effect explicit has on a default constructor.

云柯 2024-09-08 03:51:09

您不想将这些构造函数中的任何一个标记为显式 - 编译器需要隐式使用它们,特别是复制构造函数。您想通过将它们标记为显式来实现什么目的?

You don't want to mark either of those constructors as explicit - the compiler needs to use both of them, particularly the copy constructor, implicitly. What are you trying to achieve by marking them explicit?

多情出卖 2024-09-08 03:51:09

首先,默认构造函数和复制构造函数都不应该是显式的。如果构造函数采用某种其他类型的单个参数,则只需将构造函数设为显式,以防止从该类型进行隐式转换。复制构造函数引用类本身,因此不存在不必要的转换的危险。

其次,确保复制构造函数采用 const 引用。

第三,Foo f; 是拥有类 foo 的默认构造对象的正确方法。请注意, Foo f(); 是错误的,因为编译器会将其解释为函数 f() 的声明,该函数返回类 Foo 的对象代码>.

第四,如果您编写了自己的复制构造函数,那么您还应该编写赋值运算符。


class Foo
{
  Foo() {} // no need to make explicit.  Nothing to convert from.

  Foo(const &Foo f) {} // again, nothing wrong with conversion from Foo to Foo

  explicit Foo(int a) {}  // need explicit to prevent accidental passing of an int
                          // to a function that takes Foo as an argument
};

First, neither the default constructor nor the copy constructor should ever be explicit. You only need to make a constructor explicit if it takes a single argument of some other type, to prevent implicit conversion from that type. The copy constructor takes a reference to the class itself, so there is no danger of an unwanted conversion.

Second, make sure that the copy constructor takes a const reference.

Third, Foo f; is the right way to have a default-constructed object of class foo. Note that Foo f(); is wrong, because the compiler will interpret that as a declaration of function f() which returns an object of class Foo.

Fourth, if you have written your own copy constructor, then you should also write the assignment operator.


class Foo
{
  Foo() {} // no need to make explicit.  Nothing to convert from.

  Foo(const &Foo f) {} // again, nothing wrong with conversion from Foo to Foo

  explicit Foo(int a) {}  // need explicit to prevent accidental passing of an int
                          // to a function that takes Foo as an argument
};

把时间冻结 2024-09-08 03:51:09

尝试不显式?我认为:

Foo foo = Foo()

创建一个隐式副本,因此不会触发显式复制构造函数。

编辑:

这只是答案的一半。请参阅 Charles Bailey 或 UncleBens 的帖子了解为什么 const 是必要的。

Try without the explicit? I think that:

Foo foo = Foo()

creates an implicit copy, thus the explicit copy constructor doesn't get triggered.

Edit:

This is only half the answer. See Charles Bailey or UncleBens post for why const is necessary.

羞稚 2024-09-08 03:51:09

复制构造函数不应该是显式的(这使得它在此处和许多其他完全合理的上下文中无法调用,例如按值传递或返回时)。

接下来,它应该通过 const 引用获取参数,否则它无法绑定到临时变量。

Foo f = Foo();
        ^^^^^
          |
          --- this is a temporary that cannot be passed to a function
              that accepts a non-const reference

此外,没有理由使默认构造函数显式:此关键字仅对可以仅使用一个参数调用的构造函数(复制构造函数除外)有意义,在这种情况下,它会阻止隐式转换通过该构造函数将其他类型放入 Foo 中。例如,如果采用 int 的构造函数是显式,则此类情况将无法编译:

Foo f;
f = 1;  //assuming no operator= overload for (types convertible from) int
        //this implicitly performs f = Foo(1);

Foo g = 10;

void x(Foo);
x(20);

总而言之:此外

class Foo
{
public:
    Foo();
    Foo(const Foo&);
    //...
};

Foo x = Foo();

,如果这些构造函数都不打算执行此操作任何东西,你根本不需要定义它们 - 编译器将自动提供它们(如果你定义任何其他构造函数,则默认构造函数不会自动生成)。

A copy constructor shouldn't be explicit (which makes it uncallable here and in many other perfectly reasonable contexts, such as when passing or returning by value).

Next it should take the argument by const reference, since otherwise it can't bind to temporaries.

Foo f = Foo();
        ^^^^^
          |
          --- this is a temporary that cannot be passed to a function
              that accepts a non-const reference

Furthermore, there is no reason to make the default constructor explicit: this keyword only makes sense for constructors (other than the copy constructor) that can be called with exactly one argument, in which case it prevents implicit conversions of other types into Foo via that constructor. For example, if a constructor taking an int were explicit, situations like these wouldn't compile:

Foo f;
f = 1;  //assuming no operator= overload for (types convertible from) int
        //this implicitly performs f = Foo(1);

Foo g = 10;

void x(Foo);
x(20);

All in all:

class Foo
{
public:
    Foo();
    Foo(const Foo&);
    //...
};

Foo x = Foo();

And furthermore, if neither of those constructors is meant to do anything, you needn't define them at all - the compiler will provide them automatically (if you define any other constructors, the default constructor will not be automatically generated, though).

是伱的 2024-09-08 03:51:09
Foo d = Foo();

应该是

Foo d;

第一行创建一个Foo实例,然后将其复制到d;

Foo d = Foo();

should be

Foo d;

The first line creates a Foo instance and then copies it to d;

羞稚 2024-09-08 03:51:09

你的问题出在实例化上。您不需要 Foo d = Foo(); 作为默认构造函数。

保持您的类相同,但尝试这样进行实例化:

Foo d;

事实上,您甚至不需要 Foo d = Foo(arguments); 来使用参数进行构造。应该是这样的:

Foo d(arguments);

Your problem is in the instantiation. You don't need Foo d = Foo(); for a default constructor.

Keep your class the same, but try this for instantiation:

Foo d;

In fact, you don't even need Foo d = Foo(arguments); for constructing with parameters. That should be like this:

Foo d(arguments);
梦言归人 2024-09-08 03:51:09

编译器告诉你......使用这个:

Foo(const Foo&) {}

The compiler is telling you... Use this:

Foo(const Foo&) {}
残龙傲雪 2024-09-08 03:51:09

您可以通过两种方式解决该问题。其中之一(Randolpho 已经建议)是消除使用复制器。另一种是编写一个适当的复制器:

Foo (Foo const &) {}

您通常想要两者兼而有之。

编辑:看看它,我最后的评论很容易被误解。相当多的类根本不需要复制构造函数,但是如果您确实需要复制构造函数,它通常应该具有上面的形式(不明确,并且采用const 引用作为参数)。

You can cure the problem in either of two ways. One (already suggested by Randolpho) is to eliminate using the copy ctor. The other is to write a proper copy ctor:

Foo (Foo const &) {}

You generally want to do both.

Edit: Looking at it, my last comment is easy to mis-construe. Quite a few classes do not need a copy ctor at all, but if you do need a copy ctor, it should normally have the form above (not explicit, and taking a const reference as the parameter).

堇色安年 2024-09-08 03:51:09
class Foo
{
public:
    explicit Foo() {}
    explicit Foo(const Foo&) {}
};

Foo d = Foo()
class Foo
{
public:
    explicit Foo() {}
    explicit Foo(const Foo&) {}
};

Foo d = Foo()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文