2013-04-27 6 views
1
public: 
    string str; 

    Test(string& str){ 
     this->str=str; 
     cout<<"constructor"<<endl; 
    } 


}; 

int main() { 
    Test t="test"; 
    return 0; 
} 

почему всплывающее окно».. \ SRC \ test.cpp: 30: 9: ошибка: преобразование из«сопзИте полукокс [5] 'для нескалярного типа' Test 'запрошен "?ошибка: преобразование из 'сопзИте полукокс [5] для нескалярного типа в C++

но почему это нормально в следующем коде?

#include <iostream> 
using namespace std; 

class Test{ 

public: 
    string str; 

    Test(string str){ 
     this->str=str; 
     cout<<"constructor"<<endl; 
    } 

    Test(const Test &test){ 
     cout<<"copy constructor"<<endl; 
     this->str=test.str; 
    } 

}; 

int main() { 
    Test t=Test("test"); 
    return 0; 
} 
+0

@Petesh Это строительство, а не назначение. –

+0

, потому что строка имеет конструктор по умолчанию для const char *. –

+0

неправильно прочитал код, удалил неточный комментарий. немного походите на маппет для создания комментария – Petesh

ответ

8
Test t="test"; 

Это пытается:

  • Преобразование строкового литерала (который представляет собой массив символов, char[5]) во временную string
  • Преобразование временного string в Test

Это терпит неудачу по двум причинам:

  • неявное последовательность преобразования не может включать в себя более одного пользовательского преобразования. Здесь нужны два.
  • Временное не может связываться с неконстантным lvalue ссылка, это то, что хочет ваш конструктор преобразования Test(string&).

Ваш второй пример фиксирует эти проблемы:

  • Создание преобразования из string в Test явной, Test(...). Теперь существует только одно неявное преобразование: от char[5] до string. Обратите внимание, что это скорее верный способ его инициализации; Test t("test") будет делать то же самое.
  • Объявление конструктора преобразования принимает значение string по значению, а не по ссылке. Ссылка на константу, const string&, также будет работать, как и const char*.

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

+1

Это всегда беспокоило меня, теперь назначая строковый литерал, почему компилятор создаст объект строки temp? это определенная языком вещь как таковая? и во время создания объекта, если obect перегрузил '=', почему он запускает конструкцию назначения копирования вместо перегруженного оператора? –

+0

@ Koushik: поскольку единственный подходящий конструктор для 'Test' (после того, как он исправлен для принятия значения или ссылки' const'), требуется строковый объект. Если бы был конструктор, принимающий 'const char *', тогда литерал мог быть передан непосредственно этому, не создавая временного. –

+0

В ваших комментариях к другому ответу вы говорите, что ссылка const на строку не будет работать, как я заявляю в своем ответе. [GCC согласен] (http://ideone.com/7YYR08), ​​если я ничего не пропустил. Итак, кто это? – juanchopanza

0

Просто поместите const принять "test", который является постоянным буквальным:

Test(const string& str) : str(str) { 
    ^^^^^ 
} 

и использовать его как

Test t("test"); 

or 

Test t = string("test"); 

Live code

+1

Вы попробовали просто сделать это? [Это не сработает] (http://ideone.com/V6sU4n) –

+0

@MikeSeymour это будет на MSVC, да, это недостаток компилятора MS, но я думаю, что он пытался. По крайней мере, я сделал, скомпилированный без единого предупреждения. – alexrider

+0

О, я забыл сказать, как это назвать, обновлено – deepmax

1

Вам разрешается только одиннеявное преобразование между пользовательскими типами. Ваш код имеет неявное преобразование от const char[6] (которое распадается до const char*) до std::string и от std::string до Test. По этой причине замена подписи на Test(const std::string&)will not work.

Попробуйте изменить конструктор подписи

#include <string> 

struct Test 
{ 
    Test(const char* c) : s_(c) {} 
    std::string s_; 
}; 

int main() 
{ 
    Test t = "Hello"; 
} 
0

Испытание t = "тест"; Компилятор попытается найти конструктора: Test (const char *), , но вы просто определите тест (строка &), чтобы он выскочил с ошибкой.

Ваш может попытаться определить конструктор, такие как тест (сопзЬ сЬаг *) или изменить код так: Test T = строка («тест»)

Смежные вопросы