Ситуация, есть класс Image библиотеки GDI+. В своем классе я хочу объявить public переменную — объект класса Image. Но сделать я это не могу т.к. конструктор Image который без параметров у класса Image спрятан в protected.
Я пытаюсь
class MyClass {
public:
Gdiplus::Image srcImage; // Ошибка C2248: 'Gdiplus::Image::Image' : cannot access protected member declared in class 'Gdiplus::Image'
}
Определить объект класса можно только используя Image.Image(<имя файла>, 0) constructor, но сделать это при объявлении класса я не могу т.к. путь к файлу, естественно, я определяю потом по ходу работы приложения, в зависимости от действия пользователя. В общем цель, определить один раз объект Image и дальше использовать его уже откуда угодно в этом и других моих классах.
Здравствуйте, Craftsman2004, Вы писали:
C>Определить объект класса можно только используя Image.Image(<имя файла>, 0) constructor, но сделать это при объявлении класса я не могу т.к. путь к файлу, естественно, я определяю потом по ходу работы приложения, в зависимости от действия пользователя. В общем цель, определить один раз объект Image и дальше использовать его уже откуда угодно в этом и других моих классах.
Нужно создавать MyClass там, где ты знаешь имя файла которое нужно для конструирования Image, либо делать get/set Image методы в классе, но это самое лучшее решение.
Sic luceat lux!
Re[2]: Как объявить атрибутом класса объект другого класса?
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, Craftsman2004, Вы писали:
C>>Определить объект класса можно только используя Image.Image(<имя файла>, 0) constructor, но сделать это при объявлении класса я не могу т.к. путь к файлу, естественно, я определяю потом по ходу работы приложения, в зависимости от действия пользователя. В общем цель, определить один раз объект Image и дальше использовать его уже откуда угодно в этом и других моих классах. K>Нужно создавать MyClass там, где ты знаешь имя файла которое нужно для конструирования Image, либо делать get/set Image методы в классе, но это самое лучшее решение.
Если определить где я знаю имя файла — это значит определить имя файла как константу, и пользователь не сможет ее менять, что не подходит, либо я не так понял ответ. Класс Image это класс библиотеки, в которой я не могу ничего делать (Windows GDI+).
Не люблю умников, люблю умных.
Re: Как объявить атрибутом класса объект другого класса?
class MyClass {
public:
Gdiplus::Image srcImage; // Ошибка C2248: 'Gdiplus::Image::Image' : cannot access protected member declared in class 'Gdiplus::Image'
}
Никак, т.к. его конструктор по умолчанию отмечен как "protected"
разве что добавить его инициализацию, например
Здравствуйте, Craftsman2004, Вы писали:
C>Сработало! Теперь бы осознать почему... Можешь в двух словах пояснить или ссылку дать?
Да потому что объявление указателя (переменной, хранящей адрес объекта) не ведёт к созданию объекта и даже сам указатель без инициализации указывает неведомо куда.
Зато потом ты можешь проинициализировать его, например, с помощью
srcImage = new Gdiplus::Image(параметры);
Тогда new создаст нужный объект, а переменная srcImage будет хранить его адрес.
Только нужно, чтобы для использованных тобой параметров существовал публичный конструктор.
А вообще, Прочитай Уже Этот Грёбанный Мануал.
RTFM!!!!
Re[2]: Как объявить атрибутом класса объект другого класса?
pMyClass ->srcImage пустой, не содержит файла, т.к. создался новый объект класса pMyClass. Пробовал объявить srcImage как static – не прокатывает (ошибка при компиляции). Цель сделать чтение файла один раз, а не каждый раз когда содается новый объект класса MyClass.
Здравствуйте, Craftsman2004, Вы писали:
C>Здравствуйте, SI_16, Вы писали:
SI_>>объяви указатель SI_>>
SI_>>Gdiplus::Image *srcImage;
SI_>>
C>Как я уже писал, так сработало! Спасибо! C>Далее есть какой вопрос в продолжение темы:
C>В классе MyClass я по ходу программы инициализировал объект srcImage в функции класса: C>
C>Все ок, типа документ с таким файлом теперь есть.
C>Дальше я в другом классе (Класс представления, используется Document/View архитектура) в другой функции создаю объект pMyClass: C>
C>pMyClass ->srcImage пустой, не содержит файла, т.к. создался новый объект класса pMyClass. Пробовал объявить srcImage как static – не прокатывает (ошибка при компиляции). Цель сделать чтение файла один раз, а не каждый раз когда содается новый объект класса MyClass.
W>и не забыть в конструкторе MyClass проинициализировать srcImage нулём:
Так получаю ошибку:
IntelliSense: no instance of overloaded "Gdiplus::Image::operator new" matches the argument list
argument types are: (unsigned int, const char [101], int)
На строчку W> if(srcImage) W> delete srcImage;
получаю в рантайме:
Unhandled exception at 0x013F801D in prog.exe: 0xC0000005: Access violation reading location 0xCDCDCDCD.
Здравствуйте, Craftsman2004, Вы писали:
C>На строчку W>> if(srcImage) W>> delete srcImage; C>получаю в рантайме:
попробуй поменять эти строчки местами, попробуй записать их задом наперёд. словом, отнесись к своей професси творчески — это же не математика где надо читать скучные учебники!
E>>Не надо так делать. Ты все таки почитай мануал
C>Другого варианта я не знаю, как я писал new не работает в данном случае. Если есть вариант, подскажи, пожалуйста.
ты понимаешь, что тут происходит? Ты создаешь временный объект (который живет до конца выражения) на стеке и берешь его адрес. После перехода к следующей строчке объекта уже нет, вызвался его деструктор. И у тебя указатель на область памяти, в которой когда-то был объект. Дальше эта область памяти будет перезаписана новыми данными. Попытка позвать методы этого объекта или вызвать delete srcImage вероятно приведет к расстрелу памяти или срабатыванию аппаратной защиты. А может быть видимых проявлений не будет, зато если потом в другом месте поменять одну строчку — программа упадет.
Ну т.е. это все основы, которые стоит почитать в любой книжке по плюсам, а не выяснять методом проб и ошибок.
ЗЫ С чего ты взял, что new не работает? Он чудесно работает. Напиши минимальный пример, запости сюда, если он работать не будет.
ЗЫЫ Лучше использовать не голые указатели, а unique_ptr, если есть такая возможность
ЗЫЫЫ А еще лучше выбрать время и почитать книжку
Re[6]: Как объявить атрибутом класса объект другого класса?
Здравствуйте, enji, Вы писали:
E>Здравствуйте, Craftsman2004, Вы писали:
C>>>>
C>>>> srcImage = &Gdiplus::Image(sPath,0);
C>>>>
E>>>Не надо так делать. Ты все таки почитай мануал
C>>Другого варианта я не знаю, как я писал new не работает в данном случае. Если есть вариант, подскажи, пожалуйста.
E>ты понимаешь, что тут происходит? Ты создаешь временный объект (который живет до конца выражения) на стеке и берешь его адрес. После перехода к следующей строчке объекта уже нет, вызвался его деструктор. И у тебя указатель на область памяти, в которой когда-то был объект. Дальше эта область памяти будет перезаписана новыми данными. Попытка позвать методы этого объекта или вызвать delete srcImage вероятно приведет к расстрелу памяти или срабатыванию аппаратной защиты. А может быть видимых проявлений не будет, зато если потом в другом месте поменять одну строчку — программа упадет.
E>Ну т.е. это все основы, которые стоит почитать в любой книжке по плюсам, а не выяснять методом проб и ошибок.
E>ЗЫ С чего ты взял, что new не работает? Он чудесно работает. Напиши минимальный пример, запости сюда, если он работать не будет. E>ЗЫЫ Лучше использовать не голые указатели, а unique_ptr, если есть такая возможность E>ЗЫЫЫ А еще лучше выбрать время и почитать книжку
Спасибо!
C этим разобрался, на минимальном примере тоже все изучил, все работает как надо, но:
Пробую использовать опратор new с классом из GDI+:
Gdiplus::Bitmap *srcImage;
srcImage = new Gdiplus::Bitmap(sPath,0); //получаю ошибку: no instance of overloaded "Gdiplus::Bitmap::operator new" matches the argument list, argument types are: (unsigned int, const char [101], int). Но таких аргументов ни в одном конструкторе класса Bitmap нет. Конструктора без параметров тоже нет.
srcImage = Gdiplus::Bitmap::FromFile(sPath,0); //так работает, т.к. FromFile возвращает указатель на объект. Но мне хотелось бы создать объект в heap, т.к. большой он может быть.
srcImage = Gdiplus::Bitmap::FromFile(sPath,0); //так работает, т.к. FromFile возвращает указатель на объект. Но мне хотелось бы создать объект в heap, т.к. большой он может быть.
Дык, Bitmap::FromFile как раз и возвращает указатель на обьект в хипе, разве нет?
Re[8]: Как объявить атрибутом класса объект другого класса?
Здравствуйте, DarkEld3r, Вы писали:
DE>Здравствуйте, Craftsman2004, Вы писали:
DE>
DE>srcImage = Gdiplus::Bitmap::FromFile(sPath,0); //так работает, т.к. FromFile возвращает указатель на объект. Но мне хотелось бы создать объект в heap, т.к. большой он может быть.
DE>
DE>Дык, Bitmap::FromFile как раз и возвращает указатель на обьект в хипе, разве нет?
Может быть, но подтверждение этому я не нашел на msdn. Если так, интересно он сам потом сделает delete?