@014

Почему не отрабатывает перегруженный конструктор класса?

class String
{
private:
    strCount *psc;
public:
    String()
    {
        psc = new strCount("NULL");
    }

    String(String &S)
    {
        psc = S.psc;
        (psc->count)++;
    }

    String(const char *s)
    {
        psc = new strCount(s);
    }


Если инициализировать объект так:
String s1;
String s2 = s1;

То компилятор не ругается.

А если так:
String s1 = "Нас обманули, расходимся."
то компилятор говорит что несовпадение, но есть же конструктор который принимает const Char*, почему так происходит?

Я конечно понимаю что надо инициализировать скобками(), а в с++ 11 уже и фигурными {}, но все таки, почему такое поведение?
  • Вопрос задан
  • 138 просмотров
Пригласить эксперта
Ответы на вопрос 2
@MiiNiPaa
Потому что это copy-initialization. Чтобы она работала, нужен конструктор копирования который умеет принимать в качестве параметра временные обекты. (даже учитывая то что он не будут вызван благодаря copy-elision)

Edit: en.cppreference.com/w/cpp/language/copy_initialization
If T is a class type, and the type of other is different, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary if a converting constructor was used, is then used to direct-initialize the object. The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used.
Грубо говоря сначала то, что справа неявно приводится к типу слева (при помощи конструктора) а потом используется для инициализации переменно с помощью move или copy-конструктора.
Ответ написан
Комментировать
@Mercury13
Программист на «си с крестами» и не только
Попробую рассказать об этом же более простыми словами.

Текст String s3 = "Нас обманули, расходимся."; означает вот что. Мы создаёт временную строку «Нас обманули, расходимся», а затем присваиваем её нашему s3. Конечно, компилятор это потом заоптимизирует, но это семантика языка, и ей надо следовать.

Есть два способа передать временный объект в функцию. Любую: хоть простую, хоть конструктор, хоть операцию =.
Первый — константная ссылка: String(const String &S).
Второй способ из C++11 — временная ссылка: String(String &&S).

Из-за этих временных объектов конструктор копирования и операция «присвоить», по-хорошему, должны брать const-ссылку. Вот вам аналогичный пример с операцией «присвоить».

class String
{
public:
    String() {}
    String& operator= (String& s) { return *this; }
};
String operator+ (String a, String b) { return String(); }

int main()
{
    String s1;
    String s2 = s1;
    String s4;
    s4 = s1 + s2;
}


Решается String& operator= (const String& s).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы