我在一篇文章中发现“static_cast用于非多态类型转换,而dynamic_cast用于多态类型转换”。我知道int和double不是多态类型。
但是,我还发现static_cast可以在基类和派生类之间使用。这里的多态类型是什么意思?有人说多态类型意味着具有虚函数的基类。是对的吗?这是唯一的情况吗?还有什么?任何人都可以为我详细说明这个吗?
答案 0 :(得分:18)
首先,这篇文章并不完全正确。一些 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";
}
};
稍微执行上述课程 - 另请参阅我的generic factory example:
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;
}
也可以use polymorphism without inheritance,因为它实际上是一种设计技术或风格。 (我拒绝在这里使用流行语模式 ......:P)
答案 1 :(得分:14)
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 ++中的运行时多态性。具有至少一个虚函数的类具有多态类型。
也请阅读this。已明确写出A class that declares or inherits a virtual function is called a polymorphic class.
答案 2 :(得分:8)
嗯,答案很简单。具有至少一个虚函数的类称为多态类型。这也可能只是一个析构函数。
以下是'多态类型'。
struct Test {
virtual ~Test();
};
答案 3 :(得分:2)
我认为完整的短语是“多态类型投射”。你是对的,static_cast适用于与继承无关的类型(double-int等),其他答案指出了强制转换的工作方式。
我不认为该声明暗示存在神秘的多态类型 - 只是static_cast也适用于不相关的类型。该声明虽然有点令人困惑,但澄清是很好的。
答案 4 :(得分:0)
我认为我们总是将任何类的析构函数定义/声明为虚拟,尤其是在继承树中。然后我们可以说继承树中的几乎所有类都是多态的。