2012-06-26 2 views
1

Я не понимаю что-то в C++, gcc не нравится, как я могу продолжить.
я сделал:C++: объявление в if/else: var не объявлено в этой области

if (!fModeMdi) 
      MyFirstClass* main = (MyFirstClass*) fMaino; 
    else 
      MySecondClass* main = (MySecondClass*) fMdio; 
    ... 
    ... 
    int i = main->GetNum(); 

и я получаю эту ошибку:

file.C:211:16: warning: unused variable 'main' [-Wunused-variable] 
file.C:213:15: warning: unused variable 'main' [-Wunused-variable] 
file.C:219:9: error: 'main' was not declared in this scope 

Я не могу объявить main в моем заголовке, потому что его тип зависит от fModeMdi булевых.
Как я могу решить это, пожалуйста?

+0

Есть ли иерархия наследования для двух классов? – hmjd

+0

Таким образом, должны предоставляться определения классов, а также некоторый контекст, в котором используется «основное». Мы не можем догадываться, как реализован ваш код. – mfontanini

ответ

3

Как определить переменную перед оператором if и назначить ее внутри нее?

MyFirstClass* main = 0; // use nullptr if you have access to a C++11 compiler 

if (!fModeMdi) 
    main = (MyFirstClass*) fMaino; 
else 
    main = (MySecondClass*) fMdio; 

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

+2

Что делать, если 'MySecondClass' НЕ выводится из' MyFirstClass' (прямо или косвенно)? – Nawaz

+0

До тех пор, пока мы можем предположить, что это нормально, чтобы наложить 'MySecondClass *' на 'MyFirstClass *'. – JoeFish

+0

Да, ты прав. Я предположил, что, поскольку OP использует 2 переменные, названные одинаково, эти типы были совместимы. Если он предоставит эти определения классов, может быть использован другой подход. – mfontanini

1

Следующие должны работать. В C++ область действия переменной находится внутри скобки {}, то есть она распознается только внутри скобки. Как только вы выйдете, программа не знает об этом.

MyFirstClass* main =0; 
MySecondClass* main2 =0; 

if (!fModeMdi) 
      main = (MyFirstClass*) fMaino; 
    else 
      main2 = (MySecondClass*) fMdio; 
+0

Теперь есть хотя бы один неинициализированный указатель. – hmjd

+0

извините, исправлено неинициализированное –

1

C++ является статически типизированного языка, на этой линии

int i = main->GetNum(); 

компилятор должен знать тип main во время компиляции (статический, отсюда и название). Вы не можете сделать тип main зависимым от некоторого значения fModeMdi, который известен только во время выполнения. Если каждый из ваших классов содержит метод GetNum и другие, которые вы используете после if заявления, вы можете рассмотреть вопрос о переносе их в базовый класс, как это:

class MyBaseClass { 
public: 
    virtual int GetNum() = 0; 
} 

class MyFirstClass : public MyBaseClass { 
    // ... 
}; 


class MySecondClass : public MyBaseClass { 
    // ... 
}; 

MyBaseClass* main = 0; 
if (!fModeMdi) 
      main = (MyFirstClass*) fMaino; 
    else 
      main = (MySecondClass*) fMdio; 
    ... 
    ... 

И тогда это законно

int i = main->GetNum(); 

Собственно, правильная конструкция (перемещение общих методов в базовый класс), вероятно, устранит необходимость в этом заявлении if. Это то, что называется полиморфизмом, его цель состоит в том, чтобы устранить необходимость в этих операциях if или switch.

+0

Crikey, это почти дословно то, что я собираюсь публиковать. Ты быстро! – JoeFish

2

Назначьте значение i в цикле.

int i; 
if (!fModeMdi){ 
     MyFirstClass* main = (MyFirstClass*) fMaino; 
     i = main->GetNum(); 
}else{ 
     MySecondClass* main = (MySecondClass*) fMdio; 
     i = main->GetNum(); 
} 
3

Если MyFirstClass и MySecondClass являются связаны по наследству, то вы можете сделать то, что @unkulunkulu предложил в своем ответе.

Однако, если MyFirstClass и MySecondClass являются несвязанных классов, то вы можете использовать шаблон, как:

if (!fModeMdi) 
{ 
    do_work(static_cast<MyFirstClass*>(fMaino)); 
} 
else 
{ 
    do_work(static_cast<MySecondClass*>(fMaino)); 
} 

где do_work шаблон функции, реализованный в виде:

template<typename T> 
void do_work(T *obj) 
{ 
    int i = obj->GetNum(); 

    //do rest of the work here.... 
} 

Обратите внимание, что это решение шаблона будет работать, даже если они связаны !!

0

Если main не может быть полиморфным, то то, что кажется правильным решением, является функтором (или function object). boost function и boost bind предоставляют эти библиотеки.

Игнорирование утечка памяти в программе ниже, мы связываем объект new A() или new B() их соответствующих GetNum() вызовов и завернуть их в вызываемый объект, f. При необходимости мы вызываем f().

#include <boost/function.hpp> 
#include <boost/bind.hpp> 
#include <iostream> 

class A { 
    public: 
    int GetNum() { return 0; } 
}; 

class B { 
    public: 
    int GetNum() { return 0; } 
}; 

int main(int args, char** argv) 
{ 

    bool p = true; 
    boost::function<int()> f; 
    int i; 

    if (p) { 
     f = boost::bind(&A::GetNum, new A()); 
    } 
    else { 
     f = boost::bind(&B::GetNum, new B()); 
    } 

    i = f(); 

    std::cout<<i<<std::endl; 

    return 0; 
} 

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

  • Нет связанных вопросов^_^