Это актерский состав или конструкция? - PullRequest
11 голосов
/ 30 сентября 2011

Я немного растерялся после прочтения чего-то в учебнике.Что касается кода:

void doSomeWork(const Widget& w)
{
    //Fun stuff.
}

doSomeWork(Widget(15));

doSomeWork() принимает параметр const Widget&.В учебнике Effective C ++ III говорится, что это создает временный объект Widget для передачи в doSomeWork.Он говорит, что это может быть заменено на:

doSomeWork(static_cast<Widget>(15));

, поскольку обе версии являются приведениями - очевидно, первая - это просто приведение C в стиле функции.Я бы подумал, что Widget(15) вызовет конструктор для виджета, принимающего один целочисленный параметр.

Будет ли конструктор выполняться в этом случае?

Ответы [ 7 ]

13 голосов
/ 30 сентября 2011

В C ++ этот тип выражения является формой приведения, по крайней мере, синтаксически. То есть вы используете функциональный синтаксис C ++ Widget(15) для создания временного объекта типа Widget.

Даже когда вы создаете временный объект с использованием конструктора с несколькими аргументами (как в Widget(1, 2, 3)), он все еще считается вариантом функционального приведения нотации (см. 5.2.3)

Другими словами, ваш вопрос «Является ли это составом или конструкцией» задан неправильно, поскольку он подразумевает взаимную исключительность между приведениями и «конструкциями». Они не являются взаимоисключающими. Фактически, каждое преобразование типа (будь то явное приведение или что-то более неявное) - это не что иное, как создание («конструирование») нового временного объекта целевого типа (исключая, может быть, некоторые ссылочные инициализации).

Кстати, функциональная нотация приведена в основном в C ++. Язык C не имеет функциональных стилей.

5 голосов
/ 30 сентября 2011

Коротко: Да.

Long:

Вы всегда можете сами проверить эти вещи, например ::

.
#include <iostream>

struct W
{
    W( int i )
    {
        std::cout << "W(" << i << ")\n";
    }
};

int main(int argc, const char *argv[])
{
    W w(1);
    W(2);
    static_cast<W>(3);
}

который выводит

W(1)
W(2)
W(3)
3 голосов
/ 30 сентября 2011

Оба Widget(15) и static_cast<Widget>(15) являются приведениями или преобразованием операторы, если вы предпочитаете. Оба создают новый объект назначенного тип, преобразовав 15 в Widget. Так как 15 не имеет операторы преобразования, единственный способ сделать это преобразование выделение необходимой памяти (в стеке) и вызов соответствующий конструктор. Это действительно не отличается от того, что double(15) и static_cast<double>(15), за исключением того, что мы обычно не думаем о double как имеющий конструктор (но полученный double является новым объект, отличный от 15, который имеет тип int).

3 голосов
/ 30 сентября 2011

Да, это оба :).Приведение - это синтаксическая конструкция (то есть то, что вы вводите).В этом случае конструктор вызывается как результат приведения.Так же, как конструктор будет вызван в результате ввода

Widget w(15);
1 голос
/ 30 сентября 2011

Вы сказали:

во-первых, это просто C-стиль, по-видимому,

Первый не будет компилировать в C, это не C-стиль. С-стиль выглядит как (Widget)15. Здесь создается временный объект, используя Widget::Widget(int).

Следовательно, это не бросок в стиле C.

0 голосов
/ 30 сентября 2011

Да, конечно. Любой конструктор, принимающий один параметр, будет рассматриваться как CONVERSION CONSTRUCTOR. Ваш конструктор уже принимает один параметр int, так что компилятор может "неявно" вызвать этот конструктор для соответствия аргументу (со значением 15, равным int).

Существует простой способ предотвратить такие ошибки, просто используйте ключевое слово explicit перед вашим конструктором.

Проверьте это для получения дополнительной информации.

0 голосов
/ 30 сентября 2011

Yeeeah. Вы можете заменить

Widget(15)

с

static_cast<Widget>(15)

Потому что он будет заменен обратно компилятором: D

Когда вы приводите int к Widget, компилятор ищет Widget::Widget(int); и помещает его туда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...