Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Общие переменные

324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Имеется два (например) диалоговых окна, в соответствие им определены два класса CDlg1 и CDlg2. Эти два класса практически одинаковые.
Имеется следующий код:
Код:
if(n == 1)
{
    // Инициализация диалога
    CDlg1 dlg;
}

if(n == 2)
{
    // Инициализация диалога
    CDlg2 dlg;
}

dlg.DoModal();  // Неизвестная переменная dlg


Как сделать так, чтобы DoModal() срабатывал
1.8K
20 апреля 2006 года
LM(AL/M)
332 / / 20.12.2005

если я не ошибаюсь оба класса должны иметь общего предка (что то типа CDlg), тогда делается так:

 
Код:
CDlg dlg;
switch (n)
{
  case 1: dlg = new CDlg1 (...);
  case 2: dlg = new CDlg2 (...);
  else throw something;
}

dlg.DoModal()
17K
20 апреля 2006 года
blurred
7 / / 17.04.2006
у меня вот так заработало:
Код:
void * ptr;
 if(n == 1)
 {
   ptr = new CDlg1;
 }
 if(n == 2)
 {
   ptr = new CDlg2;
 }
 ((CDlg1 * )ptr)->DoModal();
 //или
 ((CDlg2 * )ptr)->DoModal();
1.8K
20 апреля 2006 года
LM(AL/M)
332 / / 20.12.2005
но тем не менне использовать ссылку на базовый класс проще и красивее

и кстати а ты уверен что в
 
Код:
((CDlg1 * )ptr)->DoModal();
 //или
((CDlg2 * )ptr)->DoModal();


компилятор правильно разрешит ссылку на DoModal ?
324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LM(AL/M)
если я не ошибаюсь оба класса должны иметь общего предка (что то типа CDlg), тогда делается так:

 
Код:
CDlg dlg;
switch (n)
{
  case 1: dlg = new CDlg1 (...);
  case 2: dlg = new CDlg2 (...);
  else throw something;
}

dlg.DoModal()



Общий предок у них CDialog. С ним все заработало. Но самое главное не решилось. Я не могу проинициализировать свой диалог данными, т.к. базовый класс не содержит нужных мне переменных.

Но за предка спасибо

324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by blurred
у меня вот так заработало:
Код:
void * ptr;
 if(n == 1)
 {
   ptr = new CDlg1;
 }
 if(n == 2)
 {
   ptr = new CDlg2;
 }
 ((CDlg1 * )ptr)->DoModal();
 //или
 ((CDlg2 * )ptr)->DoModal();



Это конечно хорошо, но надо чтобы весь остальной код выполнялся без преобразований

1.8K
20 апреля 2006 года
LM(AL/M)
332 / / 20.12.2005
а инициализировать то как раз нужно по ссылке на нужный класс, т.е.
Код:
// Initialize
CDlg1 c1 = new ...;
CDlg2 c2 = new ...;

// Use
CDialog c = c1;
c->DoModal();

c = c2;
c->DoModal();
//etc.
17K
20 апреля 2006 года
blurred
7 / / 17.04.2006
Цитата:
Originally posted by LM(AL/M)
но тем не менне использовать ссылку на базовый класс проще и красивее


Зато нужен базовый класс, а вообще, дело вкуса :)

Цитата:
Originally posted by LM(AL/M)
и кстати а ты уверен что в
 
Код:
((CDlg1 * )ptr)->DoModal();
 //или
((CDlg2 * )ptr)->DoModal();


компилятор правильно разрешит ссылку на DoModal ?



запускал - работает
ведь DoModal метод CDialog, у него смещение относительно базового адреса объекта одинаковое для разных пользовательских диалогов

324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by blurred
Зато нужен базовый класс, а вообще, дело вкуса :)


запускал - работает
ведь DoModal метод CDialog, у него смещение относительно базового адреса объекта одинаковое для разных пользовательских диалогов



А как же обратится к переменным производных классов если их нет в базовом?

2.4K
20 апреля 2006 года
root
5 / / 13.10.2002
Код:
Цитата:Originally posted by AndreySar
Имеется два (например) диалоговых окна, в соответствие им определены два класса CDlg1 и CDlg2. Эти два класса практически одинаковые.
Имеется следующий код:
[code]

if(n == 1)
{
    // Инициализация диалога
    CDlg1 dlg;
}

if(n == 2)
{
    // Инициализация диалога
    CDlg2 dlg;
}

dlg.DoModal();  // Неизвестная переменная dlg


Как сделать так, чтобы DoModal() срабатывал

[/code]

2.4K
20 апреля 2006 года
root
5 / / 13.10.2002
Цитата:
Originally posted by root
 
Код:
 

324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by root



а что это ты такое интересное прикрепил?

17K
20 апреля 2006 года
blurred
7 / / 17.04.2006
Цитата:
Originally posted by AndreySar
А как же обратится к переменным производных классов если их нет в базовом?


На мой взгляд также. Конечно смысл в этом есть только если классы почти одинаковы, причем не только набором свойств и методов, но и порядком их объявления в декларации класса, то есть, если написать:

Код:
void * ptr;
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();

а сами классы:
Код:
class CDlg1 : public CDialog
{
// Construction
public:
CDlg1(CWnd* pParent = NULL);   // standard constructor
// Dialog Data
//{{AFX_DATA(CDlg1)
enum { IDD = IDD_DIALOG1 };
CString m_1;
//}}AFX_DATA
// и т.п.

и
Код:
class CDlg2 : public CDialog
{
// 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==...) для выбора типа, к которому преобразовывать указатель на объект
324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by blurred
На мой взгляд также. Конечно смысл в этом есть только если классы почти одинаковы, причем не только набором свойств и методов, но и порядком их объявления в декларации класса, то есть, если написать:
Код:
void * ptr;
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, а чтобы обратится к переменным класса пришлось их явно преобразовывать к моим классам.
а сами классы:
Код:
class CDlg1 : public CDialog
{
// Construction
public:
CDlg1(CWnd* pParent = NULL);   // standard constructor
// Dialog Data
//{{AFX_DATA(CDlg1)
enum { IDD = IDD_DIALOG1 };
CString m_1;
//}}AFX_DATA
// и т.п.

и
Код:
class CDlg2 : public CDialog
{
// 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, а при обращении к переменным пришлось явно преобразовывать к моему классу

324
20 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by AndreySar
Пришлось использовать компромиссный вариант:
Объект был объявлен от базового класса, в моем случае CDialog, а при обращении к переменным пришлось явно преобразовывать к моему классу



Работать то работает, а вот данные не передаются :(

534
20 апреля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by AndreySar
Работать то работает, а вот данные не передаются :(

А почему бы не объявить конструктор с параметрами?

324
21 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by HarryAxe
А почему бы не объявить конструктор с параметрами?



Тема может быть закрыта. Все получилось, правда немного не так как я хотел, но все работает исправно. Особенная благодарность blurred

3
21 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by AndreySar
Тема может быть закрыта. Все получилось, правда немного не так как я хотел, но все работает исправно. Особенная благодарность blurred


Без обид (это для blurred), то что он тебе подсказал - очень-очень плохой стиль. Это даже не стиль, а "безнаучный тык". Так делать НЕЛЬЗЯ ни в коем случае!
Лучше учиться использовать ООП и использовать правильно с самого начала.

В данном случае правильное решение - вынесение всего общего в базовый класс.
При работе со специфичными для каждого класса членами естественно надо конкретизировать. Это делается либо явно приведением указателя к указателю на дочерний класс (здесь, кстати, необходимо обеспечить валидность приведения), либо автоматически - с помощью виртуальных методов.

Код:
class CDlgBase {
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(); // Здесь через общий интерфейс идет обращение к конкретной реализации класса
324
21 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by Green
Без обид (это для blurred), то что он тебе подсказал - очень-очень плохой стиль. Это даже не стиль, а "безнаучный тык". Так делать НЕЛЬЗЯ ни в коем случае!
Лучше учиться использовать ООП и использовать правильно с самого начала.

В данном случае правильное решение - вынесение всего общего в базовый класс.
При работе со специфичными для каждого класса членами естественно надо конкретизировать. Это делается либо явно приведением указателя к указателю на дочерний класс (здесь, кстати, необходимо обеспечить валидность приведения), либо автоматически - с помощью виртуальных методов.

Код:
class CDlgBase {
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, а затем создавать на его основе нужные мне классы?
Где же ты был вчера? :) Теперь Так не охото все исправлять
Это я учту на будущее

3
21 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by AndreySar
Это конечно хорошо, но у меня базовый класс CDialog и я не имею права его изменять. Или ты предлагаешь сначала создать один общий базовый класс, производный от CDialog, а затем создавать на его основе нужные мне классы?


Канэчна!

Цитата:
Originally posted by AndreySar
Теперь Так не охото все исправлять
Это я учту на будущее


Лень - не только двигатель прогресса, но и причина катострофических ошибок.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог