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()