Общие переменные
Имеется следующий код:
{
// Инициализация диалога
CDlg1 dlg;
}
if(n == 2)
{
// Инициализация диалога
CDlg2 dlg;
}
dlg.DoModal(); // Неизвестная переменная dlg
Как сделать так, чтобы DoModal() срабатывал
если я не ошибаюсь оба класса должны иметь общего предка (что то типа CDlg), тогда делается так:
switch (n)
{
case 1: dlg = new CDlg1 (...);
case 2: dlg = new CDlg2 (...);
else throw something;
}
dlg.DoModal()
if(n == 1)
{
ptr = new CDlg1;
}
if(n == 2)
{
ptr = new CDlg2;
}
((CDlg1 * )ptr)->DoModal();
//или
((CDlg2 * )ptr)->DoModal();
и кстати а ты уверен что в
//или
((CDlg2 * )ptr)->DoModal();
компилятор правильно разрешит ссылку на DoModal ?
если я не ошибаюсь оба класса должны иметь общего предка (что то типа CDlg), тогда делается так:
switch (n)
{
case 1: dlg = new CDlg1 (...);
case 2: dlg = new CDlg2 (...);
else throw something;
}
dlg.DoModal()
Общий предок у них CDialog. С ним все заработало. Но самое главное не решилось. Я не могу проинициализировать свой диалог данными, т.к. базовый класс не содержит нужных мне переменных.
Но за предка спасибо
у меня вот так заработало:
if(n == 1)
{
ptr = new CDlg1;
}
if(n == 2)
{
ptr = new CDlg2;
}
((CDlg1 * )ptr)->DoModal();
//или
((CDlg2 * )ptr)->DoModal();
Это конечно хорошо, но надо чтобы весь остальной код выполнялся без преобразований
CDlg1 c1 = new ...;
CDlg2 c2 = new ...;
// Use
CDialog c = c1;
c->DoModal();
c = c2;
c->DoModal();
//etc.
но тем не менне использовать ссылку на базовый класс проще и красивее
Зато нужен базовый класс, а вообще, дело вкуса :)
и кстати а ты уверен что в
//или
((CDlg2 * )ptr)->DoModal();
компилятор правильно разрешит ссылку на DoModal ?
запускал - работает
ведь DoModal метод CDialog, у него смещение относительно базового адреса объекта одинаковое для разных пользовательских диалогов
Зато нужен базовый класс, а вообще, дело вкуса :)
запускал - работает
ведь DoModal метод CDialog, у него смещение относительно базового адреса объекта одинаковое для разных пользовательских диалогов
А как же обратится к переменным производных классов если их нет в базовом?
Имеется два (например) диалоговых окна, в соответствие им определены два класса CDlg1 и CDlg2. Эти два класса практически одинаковые.
Имеется следующий код:
[code]
if(n == 1)
{
// Инициализация диалога
CDlg1 dlg;
}
if(n == 2)
{
// Инициализация диалога
CDlg2 dlg;
}
dlg.DoModal(); // Неизвестная переменная dlg
Как сделать так, чтобы DoModal() срабатывал
[/code]
а что это ты такое интересное прикрепил?
А как же обратится к переменным производных классов если их нет в базовом?
На мой взгляд также. Конечно смысл в этом есть только если классы почти одинаковы, причем не только набором свойств и методов, но и порядком их объявления в декларации класса, то есть, если написать:
if(n == 1)
{
ptr = new CDlg1;
}
else
{
ptr = new CDlg2;
}
((CDlg2 * )ptr)->m_1 = "test";
((CDlg2 * )ptr)->DoModal();
//или
((CDlg1 * )ptr)->m_1 = "test";
((CDlg1 * )ptr)->DoModal();
а сами классы:
{
// Construction
public:
CDlg1(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDlg1)
enum { IDD = IDD_DIALOG1 };
CString m_1;
//}}AFX_DATA
// и т.п.
и
{
// Construction
public:
CDlg2(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDlg2)
enum { IDD = IDD_DIALOG2 };
CString m_1;
BOOL m_5;
//}}AFX_DATA
// и т.п.
то работает, а если поменять местами декларации m_5 и m_1 в классе Dlg2 - то нет. Для работы со свойствами, которые есть только в одном из двух классов, нужно вновь проверять условия (что типа if (n==...) для выбора типа, к которому преобразовывать указатель на объект
На мой взгляд также. Конечно смысл в этом есть только если классы почти одинаковы, причем не только набором свойств и методов, но и порядком их объявления в декларации класса, то есть, если написать:
if(n == 1)
{
ptr = new CDlg1;
}
else
{
ptr = new CDlg2;
}
((CDlg2 * )ptr)->m_1 = "test";
((CDlg2 * )ptr)->DoModal();
//или
((CDlg1 * )ptr)->m_1 = "test";
((CDlg1 * )ptr)->DoModal();
Я использовал компромиссный вариант:
Объект класса объявлен как базовый, т.е. CDialog, а чтобы обратится к переменным класса пришлось их явно преобразовывать к моим классам.
а сами классы:
{
// Construction
public:
CDlg1(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDlg1)
enum { IDD = IDD_DIALOG1 };
CString m_1;
//}}AFX_DATA
// и т.п.
и
{
// Construction
public:
CDlg2(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDlg2)
enum { IDD = IDD_DIALOG2 };
CString m_1;
BOOL m_5;
//}}AFX_DATA
// и т.п.
то работает, а если поменять местами декларации m_5 и m_1 в классе Dlg2 - то нет. Для работы со свойствами, которые есть только в одном из двух классов, нужно вновь проверять условия (что типа if (n==...) для выбора типа, к которому преобразовывать указатель на объект
Пришлось использовать компромиссный вариант:
Объект был объявлен от базового класса, в моем случае CDialog, а при обращении к переменным пришлось явно преобразовывать к моему классу
Пришлось использовать компромиссный вариант:
Объект был объявлен от базового класса, в моем случае CDialog, а при обращении к переменным пришлось явно преобразовывать к моему классу
Работать то работает, а вот данные не передаются :(
Работать то работает, а вот данные не передаются :(
А почему бы не объявить конструктор с параметрами?
А почему бы не объявить конструктор с параметрами?
Тема может быть закрыта. Все получилось, правда немного не так как я хотел, но все работает исправно. Особенная благодарность blurred
Тема может быть закрыта. Все получилось, правда немного не так как я хотел, но все работает исправно. Особенная благодарность blurred
Без обид (это для blurred), то что он тебе подсказал - очень-очень плохой стиль. Это даже не стиль, а "безнаучный тык". Так делать НЕЛЬЗЯ ни в коем случае!
Лучше учиться использовать ООП и использовать правильно с самого начала.
В данном случае правильное решение - вынесение всего общего в базовый класс.
При работе со специфичными для каждого класса членами естественно надо конкретизировать. Это делается либо явно приведением указателя к указателю на дочерний класс (здесь, кстати, необходимо обеспечить валидность приведения), либо автоматически - с помощью виртуальных методов.
public:
int commonParam;
void DoModal();
virtual int getSpecific() = 0;
};
class CDlg1 :public CDlgBase {
public:
int specParam;
int getSpecific() {
return specParam;
}
};
class CDlg2 :public CDlgBase {
public:
int getSpecific() {
return 0;
}
};
CDlgBase* dlg;
switch(n)
{
case 1: {
CDlg1* dlg1 = new CDlg1;
dlg1->specParam = 5; // некоторый специфичный параметр
dlg = dlg1;
}
break;
case 2: { // а здесь без специфичного параметра
dlg = new CDlg2;
}
break;
}
dlg->commonParam = 7; // общий для обоих классов параметр
dlg->DoModal(); // Вызов общего для обоих классов метода
int val = dlg->getSpecific(); // Здесь через общий интерфейс идет обращение к конкретной реализации класса
Без обид (это для blurred), то что он тебе подсказал - очень-очень плохой стиль. Это даже не стиль, а "безнаучный тык". Так делать НЕЛЬЗЯ ни в коем случае!
Лучше учиться использовать ООП и использовать правильно с самого начала.
В данном случае правильное решение - вынесение всего общего в базовый класс.
При работе со специфичными для каждого класса членами естественно надо конкретизировать. Это делается либо явно приведением указателя к указателю на дочерний класс (здесь, кстати, необходимо обеспечить валидность приведения), либо автоматически - с помощью виртуальных методов.
public:
int commonParam;
void DoModal();
virtual int getSpecific() = 0;
};
class CDlg1 :public CDlgBase {
public:
int specParam;
int getSpecific() {
return specParam;
}
};
class CDlg2 :public CDlgBase {
public:
int getSpecific() {
return 0;
}
};
CDlgBase* dlg;
switch(n)
{
case 1: {
CDlg1* dlg1 = new CDlg1;
dlg1->specParam = 5; // некоторый специфичный параметр
dlg = dlg1;
}
break;
case 2: { // а здесь без специфичного параметра
dlg = new CDlg2;
}
break;
}
dlg->commonParam = 7; // общий для обоих классов параметр
dlg->DoModal(); // Вызов общего для обоих классов метода
int val = dlg->getSpecific(); // Здесь через общий интерфейс идет обращение к конкретной реализации класса
Это конечно хорошо, но у меня базовый класс CDialog и я не имею права его изменять. Или ты предлагаешь сначала создать один общий базовый класс, производный от CDialog, а затем создавать на его основе нужные мне классы?
Где же ты был вчера? :) Теперь Так не охото все исправлять
Это я учту на будущее
Это конечно хорошо, но у меня базовый класс CDialog и я не имею права его изменять. Или ты предлагаешь сначала создать один общий базовый класс, производный от CDialog, а затем создавать на его основе нужные мне классы?
Канэчна!
Теперь Так не охото все исправлять
Это я учту на будущее
Лень - не только двигатель прогресса, но и причина катострофических ошибок.