2014-09-04 2 views
0

Что вы думаете об этой части кода C++:- это неявное понижение, используя новый ОК?

Polygon* p; 
if(shape=="Rectangle") 
    p = new Rectangle(); 
else if(shape=="Triangle") 
    p = new Triangle(); 
else 
    exit(EXIT_FAILURE); 

где прямоугольник и треугольник проистекают из базового класса Polygon.

Идея заключается в том, что мне нужно использовать определенные методы из производных классов, не зная, какой класс мне нужен, пока программа не запустится. Есть ли лучший способ сделать это? Он компилируется, но мне интересно, вызывается ли деструктор выбранного производного класса так, чтобы определенные переменные были правильно освобождены.

Вспомогательный вопрос: включает ли операция dynamic_cast копирование данных?

Спасибо :)

EDIT:

Спасибо за все эти очень поучительные ответы.

Теперь, скажем, метод

bool isIsosceles() 

осуществляется в треугольнике, но не в прямоугольнике.

Затем вызова сразу

p->isIsosceles() 

, очевидно, не в состоянии.

Мои первые идеи будут либо:

Declare и осуществлять isIsosceles() в качестве виртуального метода в базовом классе Polygon, как

virtual bool isIsosceles() 
{ 
    cout << "Isosceles means nothing to me." << endl; 
    exit(EXIT_FAILURE); 
} 

или использование dynamic_cast в если заявление.

Является ли любой из этих вариантов хорошей практикой здесь?

Большое спасибо

+0

_ «Есть ли лучший способ сделать это?» _ Да, используйте интеллектуальные указатели вместо управления памятью с помощью 'new()' и 'delete' самостоятельно. Также я бы рекомендовал поместить этот код в назначенный заводский класс, который отвечает за создание правильных типов. –

+0

'dynamic_cast' не включает в себя копию данных, но это связано с использованием информации типа времени выполнения (RTTI). Его часто считают медленной операцией. – YoungJohn

ответ

1

будет работать, если вы помните, чтобы delete p и деструктор Polygon является virtual. Это очень важно.

Лучшая альтернатива заключается в том, чтобы обернуть его умным указателем.

0

Это не удручающее положение. Здесь вы используете полиморфизм, т. Е. Создаете объект некоторого производного типа, который вы будете использовать как объект своего базового типа.

Вы можете сделать это, но как и все, что вы назначаете новым, используйте delete. Другое дело, следует отметить, что вам нужен виртуальный деструктор в Polygon, как это:

class Polygon { 

    virtual ~Polygon(); 
} 

в противном случае вы будете в конечном итоге с объектом нарезку, то есть вы будете иметь объекты «половинной удаленные».

Дополнительное примечание: FYI, понижающее приведение будет, используя классы, выполнив следующие действия:

Polygon* polygon = new Triangle(); 

Triangle* triangle = dynamic_cast<Triangle*>(polygon); 

// Check that we effectively had a triangle under this polygon pointer 
if(triangle){ 
    //do something with the triangle 
} 
1

подразумевается понижающее приведение с использованием нового ОК?

Здесь нет «понижения»: это прямое использование полиморфного поведения. Ваш Polygon * является указателем на базовый класс; ваш код построения создает объект, который абстрагирует реализацию с помощью виртуальных функций-членов.

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

При условии, что деструктор в базовом классе является виртуальным (что должно быть) освободить объект через указатель на базовый класс будет делать все правильно:

delete p; 

Есть ли лучший способ делая это?

Вы можете использовать std::unique_ptr<Polygon> автоматизировать процесс удаления вашего Polygon объекта. Использование умного указателя уничтожит объект, когда указатель выходит за пределы области видимости.

Выполняется ли операция dynamic_cast с копией данных?

Я предполагаю, что вы не имеете использование для dynamic_cast здесь, потому что Polygon объявляет виртуальные функции-члены для всех операций, представляющих интерес. Однако, когда вы делаете dynamic_cast, копирование данных не происходит. Система проверяет, разрешена ли акция, и либо дает вам правильный указатель на литье, либо возвращает nullptr.

0

Идея заключается в том, что мне нужно использовать определенные методы из производных классов, не зная, какой класс мне нужен, пока программа не запустится.

Этот вид поражения цели полиморфизма, который позволяет выполнять операции БЕЗ ЗНАНИЯ, с каким производным типом вы работаете.

Есть ли лучший способ сделать это?

Это зависит от того, что вы на самом деле пытаетесь выполнить в первую очередь. То, что вы показали, может быть реализовано, например, как часть фабрики классов. Бу, вы не показали, как вы используете эти объекты после их создания, поэтому сложно сказать, поступаете ли вы правильно или нет.

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

Это будет только в случае, если ~Polygon() объявлен как virtual.

Выполняется ли операция dynamic_cast с копией данных?

№ A dynamic_cast просто выполняет поиск во время выполнения, чтобы получить указатель на другой раздел VMT для одного и того же объекта.