Я нашел в одной статье, говоря "static_cast, используется для неполиморфного преобразования типа, и dynamic_cast используется для полиморфного преобразования типа". Я понимаю, что интервал и дважды не является полиморфными типами.
Однако я также нашел, что static_cast может использоваться между базовым классом и производным классом. Что здесь означает полиморфный тип? Некоторые люди говорят, что полиморфный тип означает базовый класс с виртуальной функцией. Это правильно? Действительно ли это - единственная ситуация? Что еще? Может кто-либо мог разработать это для меня больше?
Прежде всего, статья не совсем правильная. Dynamic_Cast проверяет тип объекта и может потерпеть неудачу, Static_cast не проверяет и в значительной степени требует, чтобы программитор знал, что они делают (хотя это вызовет ошибки компиляции для некоторых вопиющих ошибок ), но они могут как использоваться в полиморфных ситуациях . ( Dynamic_Cast имеет дополнительное требование, чтобы по крайней мере один из участвующих типов имеет виртуальный метод.)
Полиморфизм в C ++, в двух словах, составляет с использованием объектов через отдельно определенный интерфейс . Этот интерфейс является базовым классом, и почти всегда полезно сделать это, когда у него есть виртуальные методы.
Тем не менее, редко - но можно иметь полиморфизм без каких-либо виртуальных методов; Часто это признак плохого дизайна или необходимости удовлетворять внешние требования, и из-за этого нет никакого способа дать хороший пример, который будет соответствовать здесь. («Вы будете знать, когда его использовать, когда вы видите, - это, к сожалению, лучший совет, который я могу вам здесь дать.)
Пример полиморфизма:
struct Animal {
virtual ~Animal() {}
virtual void speak() = 0;
};
struct Cat : Animal {
virtual void speak() { std::cout << "meow\n"; }
};
struct Dog : Animal {
virtual void speak() { std::cout << "wouf\n"; }
};
struct Programmer : Animal {
virtual void speak() {
std::clog << "I refuse to participate in this trite example.\n";
}
};
Тренировки вышеуказанных классов - также см. Мой Общий фабричный пример :
std::auto_ptr<Animal> new_animal(std::string const& name) {
if (name == "cat") return std::auto_ptr<Animal>(new Cat());
if (name == "dog") return std::auto_ptr<Animal>(new Dog());
if (name == "human") return std::auto_ptr<Animal>(new Programmer());
throw std::logic_error("unknown animal type");
}
int main(int argc, char** argv) try {
std::auto_ptr<Animal> p = new_animal(argc > 1 ? argv[1] : "human");
p->speak();
return 0;
}
catch (std::exception& e) {
std::clog << "error: " << e.what() << std::endl;
return 1;
}
Также возможно использовать полиморфизм без наследства , так как это действительно дизайн техника или стиль . (Я отказываюсь использовать BUZZWord здесь ...: P)
Ответ прост. Класс, имеющий хотя бы одну виртуальную функцию, называется полиморфным типом. Это тоже может быть только деструктор.
Итак, это « полиморфный тип».
struct Test {
virtual ~Test();
};
Static_Cast может выполнять преобразования между указателями на соответствующие классы, не только из полученного класса на его базу, но и из базового класса до его получения. Это гарантирует, что, по крайней мере, классы совместимы, если бы правильный объект преобразован, , но никакой проверки безопасности не выполняется во время выполнения , чтобы проверить, является ли преобразованным объектом, на самом деле является полным объектом типа назначения. Поэтому программисту в зависимости от того, чтобы преобразование было безопасным. С другой стороны, накладные расходы на проверку безопасности типа Dynamic_cast можно избежать.
Static_Cast также может использоваться для выполнения любого другого не указателя преобразования, которое также может быть выполнено неявно, как, например, для стандартных преобразований между фундаментальными типами:
double d=3.14159265;
int i = static_cast<int>(d);
Dynamic_Cast Может использоваться только с указателями и ссылками на объекты. Его целью является обеспечение того, чтобы результат преобразования типа является действительным полным объектом запрошенного класса.
Следовательно, Dynamic_Cast - это всегда успешно , когда мы бросаем класс на один из его базовых классов.
// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;
class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };
int main () {
try {
CBase * pba = new CDerived;
CBase * pbb = new CBase;
CDerived * pd;
pd = dynamic_cast<CDerived*>(pba);
if (pd==0) cout << "Null pointer on first type-cast" << endl;
pd = dynamic_cast<CDerived*>(pbb);
if (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
}
Примечание Совместимость : Dynamic_Cast требует информации о времени выполнения (RTTI), чтобы отслеживать динамические типы. Некоторые компиляторы поддерживают эту функцию в качестве опции, который по умолчанию отключен. Это должно быть включено для проверки типа выполнения, используя Dynamic_Cast, чтобы работать правильно.
Виртуальные функции несут ответственность за полиморфизм времени выполнения в C ++. Класс, имеющий хотя бы одну виртуальную функцию, имеет полиморфный тип.
Прочитайте это тоже. Было четко написано, что класс, который объявляет или наследует виртуальную функцию, называется полиморфным классом.
Я думаю, что полная фраза - это «полиморфный тип , отливка ». Вы правы, что Static_cast работает на типов, которые не связаны от наследования (Double - Int, и т. Д.), а остальные ответы указывают на то, как работают отказ.
Я не думаю, что утверждение подразумевает существование мифического полиморфного типа, хотя - только что Static_Cast также работает на не связанных типах. Заявление было немного запутанным, хотя и хорошо уточнить.