Синтаксис создания класса - PullRequest
2 голосов
/ 29 октября 2011

Меня всегда учили, что

1. Class c(arg);

и

2. Class c = arg;

- это два абсолютно эквивалентных утверждения, но посмотрите на эту ситуацию.

#include <iostream>

class Intermediary {
};

class Left {
  public:
    Left(const Intermediary &) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }   
};

class Right {
  public:
    // The argument is there just so that the example can work, see below
    Right(int) { 
        std::cout << __PRETTY_FUNCTION__  << std::endl;
    }

    operator Intermediary () const {
        std::cout << __PRETTY_FUNCTION__  << std::endl;

        return Intermediary();    
    }
};

Теперь, если я сделаю это:

Left l = Right(0);

Компилятор будет жаловаться

error: conversion from Right to non-scalar type Left requested

Но если я сделаю это:

Left l(Right(0)); 

Тогда все компилируется и вывод

Right::Right(int)
Right::operator Intermediary() const
Left::Left(const Intermediary&)

Однако, если я сделаю это:

Left l = (Intermediary)Right(0);

, то все снова будет скомпилировано, и результат будет такой же, как и выше.

Очевидно,

1. Class c(arg);

и

2. Class c = arg;

не одинаковы, но почему бы и нет, и в чем разница?Я не мог ничего найти об этом в Интернете.

1 Ответ

5 голосов
/ 29 октября 2011

Меня всегда учили, что Class c(arg); и Class c = arg; - два абсолютно эквивалентных утверждения, но посмотрите на эту ситуацию.

Оказывается, они не эквивалентны. Первый создает Class c из arg, а второй создает Class из arg, а затем копирует-конструирует Class c из него. Обратите внимание, что реализации разрешено отменять эту копию, и это обычно происходит.

Left l = Right(0);

Для этого требуется преобразование из Right в Intermediary и одного из Intermediary в Left. Эти два последовательных пользовательских преобразования не разрешены стандартом, вы должны сделать хотя бы одно из них явным, как вы делаете это с:

Left l = (Intermediary)Right(0);
...