1) Установка первой панели:
JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());
2) Замена панели:
frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());
Также обратите внимание, что вы должны сделать это в потоке события, чтобы обеспечить это использует SwingUtilities.invokeLater или SwingWorker
Если вы используете приведение в стиле C для преобразования в Alpha*
, аналогично static_cast перед использованием динамического приведения, то динамическое приведение не дает никакого эффекта. здесь ваш код выполняется, потому что оба класса имеют одинаковый интерфейс, но в действительности это неопределенное поведение.
Обычно вы хотите использовать динамическое приведение к восходящему / нисходящему из / в базовый класс в / из его производного класса.
Например, если мы добавим базовый интерфейс, затем преобразуем указатель void *
в этот базовый класс, а затем используем динамическое приведение, чтобы выполнить преобразование, код работает как положено и печатается только один раз. ]
#include <stdio.h>
class Speaker {
public:
virtual void Speak() = 0;
};
class Alpha: public Speaker {
public:
virtual void Speak() { printf("A"); }
};
class Beta: public Speaker {
public:
virtual void Speak() { printf("B"); }
};
int main(){
void *p = new Alpha;
// Convert to base type, using static_cast
Speaker *s = static_cast<Speaker *>(p);
// Attempt Upcasts
Alpha*a = dynamic_cast<Alpha*>(s);
Beta*b = dynamic_cast<Beta*>(s);
// See if it worked
if (a)
a->Speak();
if (b)
b->Speak();
return 0;
}
Выходы: A
Вы должны знать тип, из которого был преобразован указатель void. Если вы не знаете динамический тип, то вы должны создать указатель void из указателя на базу. Если вы не знаете тип указателя, из которого был создан указатель void, вы не сможете использовать указатель void.
Учитывая, что указатель void был преобразован из Alpha*
, вы можете преобразовать его обратно, используя статическое приведение:
auto a_ptr = static_cast<Alpha*>(p);
Затем вы можете использовать dynamic_cast
для преобразования в производный тип. [119 ]
if(auto d_ptr = dynamic_cast<DerivedAlpha*>(a_ptr)) {
// do stuff with DerivedAlpha
Если динамический тип не равен DerivedAlpha
, динамическое приведение будет безопасно возвращать ноль. Вы не можете динамически отбрасывать от иерархии типов. Поскольку Alpha
и Beta
не связаны какой-либо структурой наследования, они не могут быть динамически преобразованы взаимно.
Выражение Alpha*a = dynamic_cast<Alpha*>((Alpha*)p);
сначала преобразует p
в Alpha*
с явным приведением стиля c . Затем полученный результат Alpha*
пропускается через dynamic_cast<Alpha*>
. Использование dynamic_cast<T*>
для указателя T*
(указатель того же типа, к которому вы пытаетесь привести) всегда будет обеспечивать входной указатель. Его нельзя использовать для подтверждения правильности указателя. Из cppreference для dynamic_cast<new_type>(expression)
:
Если тип
blockquote>expression
точноnew_type
или менее квалифицированная по cv версияnew_type
, результатом является значениеexpression
, с типомnew_type
.В результате код всегда будет компилироваться и выполняться, а система типов не будет вас защищать. Но итоговое поведение не определено. В случае
Beta*b = dynamic_cast<Beta*>((Beta*)p);
вы говорите компилятору доверять, чтоp
являетсяBeta*
, но это не так. Разыменование результирующего указателя является неопределенным поведением, иdynamic_cast
не может защитить вас от этой ошибки.Если вы попытаетесь удалить явное преобразование типов, вы получите ошибку компилятора.
dynamic_cast
требует указателя или ссылки на полный тип, аvoid
не является полным типом. Вам нужно будет найти способ отследить фактический тип, указанный вам, и явно преобразоватьp
в этот тип указателя перед использованиемdynamic_cast
. Хотя в этот момент, если вы уже знаете тип, к которому нужно применить приведение, это может больше не понадобиться.Попробуйте использовать общий базовый тип вместо этого или, возможно, используйте
std::variant
илиstd::any
, если это необходимо.
Единственное , что вы можете сделать с помощью указателя void*
, это привести его обратно к точно того же типа, что и указатель, приведенный к void*
в первом место. Поведение при выполнении чего-либо еще не определено.
Что вы могли бы сделать в вашем случае, так это определить
class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};
и сделать его базовым классом для Alpha
и Beta
. Затем обведите указатель Base*
, а не void*
, и поместите ваши dynamic_cast
прямо на p
.
Также отметим, что если вы объявите virtual void Speak() = 0;
в Base
, то ваш код в main
станет просто
int main(){
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}
Как правило, любые типы нежелательны. [ 1119]