什么是C ++中的多态类型?

时间:2010-01-09 04:39:00

标签: c++

我在一篇文章中发现“static_cast用于非多态类型转换,而dynamic_cast用于多态类型转换”。我知道int和double不是多态类型。

但是,我还发现static_cast可以在基类和派生类之间使用。这里的多态类型是什么意思?有人说多态类型意味着具有虚函数的基类。是对的吗?这是唯一的情况吗?还有什么?任何人都可以为我详细说明这个吗?

5 个答案:

答案 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 ++中的运行时多态性。具有至少一个虚函数的类具有多态类型。

Read More....

也请阅读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)

我认为我们总是将任何类的析构函数定义/声明为虚拟,尤其是在继承树中。然后我们可以说继承树中的几乎所有类都是多态的。