首页 文章

什么是C中的多态类型?

提问于
浏览
26

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

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

5 回答

  • 17

    首先,这篇文章并不完全正确 . dynamic_cast检查对象的类型并且可能失败,static_cast不检查并且很大程度上要求程序员知道他们正在做什么(虽然它会针对一些严重的错误发出编译错误),但 they may both be used in polymorphic situations . (dynamic_cast还有一个附加要求,即至少有一个涉及的类型有一个虚方法 . )

    简而言之,C中的多态性是 using objects through a separately-defined interface . 该接口是基类,当它具有虚拟方法时,它几乎总是有用 .

    然而,在没有任何虚拟方法的情况下拥有多态性是罕见但可能的;通常这是一个糟糕的设计或不得不满足外部要求的标志,因此,没有办法给出一个适合这里的好例子 . (“当你看到它时,你会知道什么时候使用它”,不幸的是,这是我能给你的最佳建议 . )

    多态性例子:

    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)

  • 14

    static_cast 可以在指向相关类的指针之间执行转换,不仅可以从派生类到其基类,还可以从基类到其派生类 . 这确保了如果转换了正确的对象,至少类是兼容的, but no safety check is performed during runtime 以检查被转换的对象实际上是否是目标类型的完整对象 . 因此,程序员应确保转换是安全的 . 另一方面,避免了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;
     }
    

    Compatibility note :dynamic_cast需要运行时类型信息(RTTI)来跟踪动态类型 . 某些编译器支持此功能作为默认禁用的选项 . 必须为运行时类型检查启用此选项,以使用dynamic_cast正常工作 .

    Virtual Functions 负责C中的运行时多态性 . 具有至少一个虚函数的类具有多态类型 .

    Read More....

    阅读this . 已经清楚地写了 A class that declares or inherits a virtual function is called a polymorphic class.

  • 2

    嗯,答案很简单 . 具有至少一个虚函数的类称为多态类型 . 这也可能只是一个析构函数 .

    所以以下是'多态类型' .

    struct Test {
      virtual ~Test();
    };
    
  • -1

    我认为完整的短语是“多态型铸造” . 你是对的,static_cast适用于与继承无关的类型(double-int等),其他答案指出了强制转换的工作方式 .

    我不认为该声明暗示存在神秘的多态类型 - 只是static_cast也适用于不相关的类型 . 该声明虽然有点令人困惑,但澄清一下是件好事 .

  • 7

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

相关问题