C ++ - оператор создания вызова при создании вместо конструктора копирования - PullRequest
0 голосов
/ 17 сентября 2010

Я хочу обеспечить явное преобразование между структурами, похожими на нативные типы:

int i1;
i1 = some_float; // this generates a warning
i1 = int(some_float): // this is OK
int i3 = some_float; // this generates a warning

Я думал использовать оператор присваивания и конструктор копирования, чтобы сделать одно и то же, но поведение отличается:

Struct s1;
s1 = other_struct; // this calls the assignment operator which generates my warning
s1 = Struct(other_struct) // this calls the copy constructor to generate a new Struct and then passes that new instance to s1's assignment operator
Struct s3 = other_struct; // this calls the COPY CONSTRUCTOR and succeeds with no warning

Есть ли какие-нибудь хитрости, чтобы получить этот третий случай Struct s3 = other_struct; Сконструировать s3 с конструктором по умолчанию, а затем вызвать оператор присваивания?

Все это компилируется и выполняется так, как должно.Поведение C ++ по умолчанию заключается в вызове конструктора копирования вместо оператора присваивания, когда вы создаете новый экземпляр , а вызывает конструктор копирования сразу (т.е. MyStruct s = other_struct; становится MyStruct s(other_struct); не MyStruct s; s = other_struct;Мне просто интересно, есть ли какие-нибудь хитрости, чтобы обойти это.

РЕДАКТИРОВАТЬ: "Явное" ключевое слово как раз то, что мне нужно!

class foo {
    foo(const foo& f) { ... }
    explicit foo(const bar& b) { ... }
    foo& operator =(const foo& f) { ... }
};

foo f;
bar b;
foo f2 = f; // this works
foo f3 = b; // this doesn't, thanks to the explicit keyword!
foo f4 = foo(b); // this works - you're forced to do an "explicit conversion"

Ответы [ 4 ]

4 голосов
/ 17 сентября 2010

Отказ от ответственности: я готов принять отрицательные оценки по этому вопросу, так как это не отвечает на вопрос.Но это может быть полезно для OP.

Я думаю, что очень плохая идея думать о конструкторе копирования как о конструкции по умолчанию + присваивании.И наоборот:

struct some_struct
{
    some_struct();  // If you want a default constructor, fine
    some_struct(some_struct const&); // Implement it in the most natural way
    some_struct(foo const&);         // Implement it in the most natural way

    void swap(some_struct&) throw(); // Implement it in the most efficient way

    // Google "copy and swap idiom" for this one
    some_struct& operator=(some_struct x) { x.swap(*this); return *this; }

    // Same idea
    some_struct& operator=(foo const& x)
    {
        some_struct tmp(x);
        tmp.swap(*this);
        return *this;
    }
};

Реализация всего этого так надежна, и это лучшее, что вы можете получить с точки зрения семантики преобразования в C ++, так что способ идти сюда.

3 голосов
/ 17 сентября 2010

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


#include <iostream>

using namespace std;

struct bar;

struct foo {
    explicit foo() {
        cout << "In foo default constructor." << endl;
    }

    explicit foo(bar const &) {
        cout << "In foo 'bar' contructor." << endl;
    }

    foo(foo const &) {
        cout << "In foo constructor." << endl;
    }

    foo const & operator=(bar const &) {
        cout << "In foo = operator." << endl;
        return *this;
    }
};

struct bar {
    operator foo() {
        cout << "In bar cast overload." << endl;
        foo x;
        x = *this;
        return x;
    }
};

int main() {
    bar b;
    foo f = b;
    return 0;
}

Выходы:

In bar cast overload.
In foo default constructor.
In foo = operator.
In foo constructor.
In foo constructor.
2 голосов
/ 17 сентября 2010

Короче, нет.

Длинная версия ... на самом деле это все. Это просто не так, как это работает. Пришлось придумать что-то, чтобы удовлетворить требования персонажа.

0 голосов
/ 17 сентября 2010

Я так не думаю. Когда ты пишешь

Struct s3 = other_struct;

Это похоже на присваивание, но на самом деле это просто декларативный синтаксис, который вызывает конструктор.

...