конструкторы и преобразования
От: Gosha Украина  
Дата: 24.07.02 17:35
Оценка:
Всем привет!

Вот, хотел сделать что-то типа вот этого:
#include "stdafx.h"
#include <string>
using namespace std;

class SOME
{
public:
    SOME(string str=""):m_Str(str){}
    virtual ~SOME(){}
private:
    string m_Str;
};

class ANOTHER
{
public:
    ANOTHER(){}
    virtual ~ANOTHER(){}
    void SetSome(SOME some){m_Some=some;}
private:
    SOME m_Some;
};

int main(int argc, char* argv[])
{
    printf("Hello World!\n");

    ANOTHER an1;
    
    //если так...
    an1.SetSome("hello!");
    //то компилятор ругается:
    //error C2664: 'SetSome' : cannot convert parameter 1 from 'char [7]' to 'class SOME'
    //No constructor could take the source type, or constructor overload resolution was ambiguous

    //а вот так...
    an1.SetSome(string("hello!"));
    //уже работает, хотя передаем в качестве аргумента все равно
    //НЕ объект типа SOME, но тут он уже соображает его создать

    return 0;
}


Внесите, плз, ясность. Это только со string-ом и char-ом так, или есть какое-то фиксированное число... "вложенностей" что-ли при таких вот неявных преобразованиях, или как это назвать даже не знаю
Вообщем-то, оно не напрягает, но вроде как первый (нерабочий) вариант удобнее, и на этапе отладки, да и потом тоже, из виндовых функций сразу char* забирать... Или придется еще один конструктор для SOME писать? Или можно как-то по другому выкрутится?
Спасибо.
Re: Допускается одинарная вложенность
От: Кривенко Антон Владимирович  
Дата: 24.07.02 17:55
Оценка: 5 (1)
Т.е. string к SOME он преобразует. А вот char => string => SOME уже нет. Причем это, насколько я помню, оговорено стандартом (у Страуструпа есть).
Re: конструкторы и преобразования
От: Андрей Тарасевич Беларусь  
Дата: 24.07.02 18:04
Оценка: 15 (3)
Здравствуйте Gosha, Вы писали:

G>[/ccode]

G>class SOME
G>{
G>public:
G> SOME(string str=""):m_Str(str){}
G> virtual ~SOME(){}
G>private:
G> string m_Str;
G>};

G>int main(int argc, char* argv[])

G>{
G> printf("Hello World!\n");

G> ANOTHER an1;

G>
G> //если так...
G> an1.SetSome("hello!");
G> //то компилятор ругается:
G> //error C2664: 'SetSome' : cannot convert parameter 1 from 'char [7]' to 'class SOME'
G> //No constructor could take the source type, or constructor overload resolution was ambiguous

G> //а вот так...

G> an1.SetSome(string("hello!"));
G> //уже работает, хотя передаем в качестве аргумента все равно
G> //НЕ объект типа SOME, но тут он уже соображает его создать

G> return 0;

G>}
G>[/ccode]

G>Внесите, плз, ясность. Это только со string-ом и char-ом так, или есть какое-то фиксированное число... "вложенностей" что-ли при таких вот неявных преобразованиях, или как это назвать даже не знаю


При выполнении неявных преобразований компилятор имеет право применить не более одного неявного пользовательского преобразования типов (которое может быть обрамлено с обеих сторон стандартными преобразованиями). В первом случае у тебя требуется два неявных пользовательских преобразования: 'const char*' -> 'std::string' и 'std::string' -> 'SOME'. Поэтому код не компилируется. Во втором случае первое из этих преобразовний ты сделал явно, поэтому осталось только одно неявное преобразование и все компилируется нормально.

Вот еще один пример, который не компилируется по этой же причине, что многим кажется нелогичным (недавняя дискуссия в comp.std.c++). Этот пример также хорошо иллюстрирует разницу между direct-initialization, copy-initialization и assignment:

struct S
{
  operator const char*() { return "hello"; }
};

int main()
{
  S s;

  std::string str1 = s; // Copy-initialization
  // Не компилируется, т.к. требует двойного неявного пользовательского преобразования типов:
  // 'S -> const char*' и 'const char* -> std::string'

  std::string str2(s); // Direct-initialization
  // Компилируется, т.к. требует одиночного неявного пользовательского преобразования типов:
  // 'S -> const char*'

  str2 = s; // Assignment
  // Компилируется, т.к. требует одиночного неявного пользовательского преобразования типов:
  // 'S -> const char*'
}


G>Вообщем-то, оно не напрягает, но вроде как первый (нерабочий) вариант удобнее, и на этапе отладки, да и потом тоже, из виндовых функций сразу char* забирать... Или придется еще один конструктор для SOME писать? Или можно как-то по другому выкрутится?


По-видимому, лучше добавить конструктор для SOME.
Best regards,
Андрей Тарасевич
Re: конструкторы и преобразования
От: Владимир Сторожевых Россия  
Дата: 25.07.02 07:09
Оценка: 5 (1)
Здравствуйте Gosha, Вы писали:

G>Вот, хотел сделать что-то типа вот этого:

G>
G>class ANOTHER
G>{
G>public:
G>    ANOTHER(){}
G>    virtual ~ANOTHER(){}
G>    void SetSome(SOME some){m_Some=some;}
G>private:
G>    SOME m_Some;
G>};

G>int main(int argc, char* argv[])
G>{
G>    ANOTHER an1;
G>    //если так...
G>    an1.SetSome("hello!");
G>    //то компилятор ругается:
G>    //error C2664: 'SetSome' : cannot convert parameter 1 from 'char [7]' to 'class SOME'

G>    return 0;
G>


G>Вообщем-то, оно не напрягает, но вроде как первый (нерабочий) вариант удобнее, и на этапе отладки, да и потом тоже, из виндовых функций сразу char* забирать... Или придется еще один конструктор для SOME писать? Или можно как-то по другому выкрутится?


Почему бы не использовать анонимный экземпляр класса SOME ? Cинтаксис получается
достаточно понятным:
    an1.SetSome(SOME("hello!"));
Re: конструкторы и преобразования
От: Аноним  
Дата: 26.07.02 07:01
Оценка:
Здравствуйте Gosha, Вы писали:

G>Всем привет!


G>Вот, хотел сделать что-то типа вот этого:

G>
G>#include "stdafx.h"
G>#include <string>
G>using namespace std;

G>class SOME
G>{
G>public:
G>    SOME(string str=""):m_Str(str){}
G>    virtual ~SOME(){}
G>private:
G>    string m_Str;
G>};

G>class ANOTHER
G>{
G>public:
G>    ANOTHER(){}
G>    virtual ~ANOTHER(){}
G>    void SetSome(SOME some){m_Some=some;}
G>private:
G>    SOME m_Some;
G>};

G>int main(int argc, char* argv[])
G>{
G>    printf("Hello World!\n");

G>    ANOTHER an1;
G>    
G>    //если так...
G>    an1.SetSome("hello!");
G>    //то компилятор ругается:
G>    //error C2664: 'SetSome' : cannot convert parameter 1 from 'char [7]' to 'class SOME'
G>    //No constructor could take the source type, or constructor overload resolution was ambiguous

G>    //а вот так...
G>    an1.SetSome(string("hello!"));
G>    //уже работает, хотя передаем в качестве аргумента все равно
G>    //НЕ объект типа SOME, но тут он уже соображает его создать

G>    return 0;
G>}
G>


G>Внесите, плз, ясность. Это только со string-ом и char-ом так, или есть какое-то фиксированное число... "вложенностей" что-ли при таких вот неявных преобразованиях, или как это назвать даже не знаю :???:

G>Вообщем-то, оно не напрягает, но вроде как первый (нерабочий) вариант удобнее, и на этапе отладки, да и потом тоже, из виндовых функций сразу char* забирать... Или придется еще один конструктор для SOME писать? Или можно как-то по другому выкрутится?
G>Спасибо.
Добавь ещё один конструктор к SOME — SOME(const char * s) : m_Str(s) {},
и всё будет работать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.