Foo f = Foo();//нет соответствующей функции для вызова в Foo:: Foo (Foo) '... а?

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

Foo d = Foo();

error: нет соответствующей функции для вызова в Foo:: Foo (Foo) '

Я попытался изменить Foo(Foo&) на Foo(Foo), как указывает ошибка, который AFAIK не является допустимым конструктором, и, я уверен, я получаю:

ошибка: недопустимый конструктор; вы, вероятно, имели в виду "Foo (const Foo &)

Что дает? Как это разрешить? (Кстати, на GCC)

Ответ 1

В вашем конструкторе копий есть две сомнительные вещи.

Во-первых, вы сделали явный конструктор-копию (что является сомнительной задачей), поэтому вам (в теории) нужно было бы сделать:

Foo d( (Foo()) );

Во-вторых, ваш конструктор копий принимает ссылку, а не ссылку const, что означает, что вы не можете использовать ее с временным Foo.

Лично я просто удаляю explicit из конструктора-копии и при необходимости беру ссылку const.

Обратите внимание, что explicit в вашем конструкторе по умолчанию не имеет эффекта. [*] explicit влияет только на конструкторы, которые можно вызвать с помощью одного параметра. Это предотвращает их использование для неявных преобразований. Для конструкторов, которые принимают только ноль или только два или более параметров, он не имеет эффекта.

[Примечание: может быть разница между:

Foo d;

и

Foo d = Foo();

но в этом случае у вас есть объявленный пользователем конструктор по умолчанию, поэтому это не применимо.]

Edit: [*] Я только дважды проверил это, и 12.3.1 [class.conv.ctor] говорит, что вы можете создать конструктор по умолчанию explicit. В этом случае конструктор будет использоваться для выполнения инициализации по умолчанию или инициализации значения. Честно говоря, я не понимаю значение этого, как если бы у вас был объявленный пользователем конструктор, тогда он не-POD-тип и даже локальные объекты не-POD-типа инициализируются по умолчанию, если у них нет инициализатора о котором говорится в этом разделе, может быть сделано конструктором по умолчанию explicit. Возможно, кто-то может указать на угловой случай, когда он действительно имеет значение, но пока я не вижу, какой эффект explicit имеет в конструкторе по умолчанию.

Ответ 2

Вы не хотите отмечать ни один из этих конструкторов как явный - компилятор должен использовать оба из них, особенно конструктор копирования, неявно. Чего вы пытаетесь добиться, указав их явно?

Ответ 3

Во-первых, ни конструктор по умолчанию, ни конструктор копирования никогда не должны быть explicit. Вам нужно только создать конструктор explicit, если он принимает один аргумент другого типа, чтобы предотвратить неявное преобразование из этого типа. Конструктор копирования ссылается на сам класс, поэтому нет опасности нежелательного преобразования.

Во-вторых, убедитесь, что конструктор копирования принимает ссылку 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
};

Ответ 4

Попробуйте без явного? Я думаю, что:

Foo foo = Foo()

создает неявную копию, поэтому явный конструктор копирования не запускается.

Edit:

Это только половина ответа. См. Сообщение Charles Bailey или UncleBens, для чего нужен const.

Ответ 5

Конструктор копирования не должен быть явным (что делает его неприменимым здесь и во многих других вполне разумных контекстах, например, при передаче или возврате по значению).

Затем он должен принять аргумент 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();

Кроме того, если ни один из этих конструкторов не предназначен для чего-либо, вам не нужно их вообще определять - компилятор предоставит их автоматически (если вы определите любые другие конструкторы, конструктор по умолчанию не будет автоматически сгенерирован, хотя).

Ответ 6

Ваша проблема заключается в создании. Для конструктора по умолчанию вам не требуется Foo d = Foo();.

Сохраняйте свой класс тем же, но попробуйте это для создания экземпляра:

Foo d;

На самом деле вам даже не нужно Foo d = Foo(arguments); для построения с параметрами. Это должно быть так:

Foo d(arguments);

Ответ 7

Foo d = Foo();

должен быть

Foo d;

Первая строка создает экземпляр Foo и затем копирует его в d;

Ответ 8

Компилятор говорит вам... Используйте это:

Foo(const Foo&) {}

Ответ 9

Вы можете устранить проблему одним из двух способов. Один (уже предложенный Randolpho) должен устранить использование копии ctor. Другой - написать правильную копию ctor:

Foo (Foo const &) {}

Как правило, вы хотите сделать оба.

Изменить: взглянув на это, мой последний комментарий легко понять неправильно. Некоторым классам вообще не нужна копия ctor, но если вам нужна копия ctor, она должна иметь форму выше (не явную и принимать константную ссылку в качестве параметра).

Ответ 10

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

Foo d = Foo()