jjzjj

c++ - dynamic_cast 真的适用于多重继承吗?

coder 2024-02-03 原文

我想看看是否可以创建“接口(interface)”,继承它们,然后在运行时检查是否有任何随机类实现了该接口(interface)。这是我的:

struct GameObject {
    int x,y;
    std::string name;

    virtual void blah() { };
};

struct Airholder {
   int oxygen;
   int nitrogen;
};

struct Turf : public GameObject, public Airholder {
   Turf() : GameObject() {
      name = "Turf";
   }

   void blah() { };
};

void remove_air(GameObject* o) {
   Airholder* a = dynamic_cast<Airholder*>(o);
   if(!a) return;
   a->oxygen   = 0;
   a->nitrogen = 0;
};

现在,它起作用了。文档说它有效,测试示例有效。但是,直到我向 GameObject 添加虚拟方法后它才编译。问题是,我真的不知道该功能是否打算像那样使用。让我感到奇怪的是,我必须为我正在检查的类声明一个虚函数。但很明显,没有,我正在检查的类本身没有虚函数,实际上我的整个代码与虚函数无关,这是一种完全不同的方法。

所以,我想我的问题是:如果我所做的真的有效,为什么我需要一个虚函数来为我的类提供一个 vtable?为什么我不能将类声明为“运行时类型”或没有虚函数的东西?

最佳答案

标准的§ 5.2.7 说:

  1. 表达式 dynamic_cast(v) 的结果是将表达式 v 转换为类型的结果 T. T 应是一个指针或对完整类类型的引用,或“指向 cv void 的指针”。类型不得 在 dynamic_cast 中定义。 dynamic_cast 运算符不得丢弃常量 (5.2.11)。
  2. 如果 T 是一个指针类型,v 应该是一个指向完整类类型的指针的右值,结果是一个右值 类型 T。如果 T 是引用类型,则 v 应是完整类类型的左值,结果是左值 T 引用的类型。
  3. 如果 v 的类型与所需的结果类型相同(为方便起见,将在本文中称为 R 描述),或者它与 R 相同,除了 R 中的类对象类型比类更符合 cv 限定 v中的对象类型,结果为v(必要时进行转换)。
  4. 如果 v 的值是指针情况下的空指针值,则结果是 R 类型的空指针值。
  5. 如果 T 是“指向 cv1 B 的指针”并且 v 具有“指向 cv2 D 的指针”类型,使得 B 是 D 的基类,则结果为 指向 v 指向的 D 对象的唯一 B 子对象的指针。类似地,如果 T 是“对 cv1 B 的引用” v 具有类型“cv2 D”,使得 B 是 D 的基类,结果是 unique60) B 子对象的左值 v 引用的 D 对象。在指针和引用情况下,cv1 应具有相同的 cvqualification 作为或大于 cv2 的 cv 资格,并且 B 应是可访问的明确基类 D. [示例:

    结构 B {};
    结构 D : B {};
    void foo(D* dp)
    {
    B* bp = dynamic_cast(dp);//等同于 B* bp = dp;

    ——例子结束]

  6. 否则,v 应是指向多态类型 (10.3) 的指针或左值。

并且要使类型多态,它需要一个虚函数,根据§ 10.3:

Virtual functions support dynamic binding and object-oriented programming. A class that declares or inherits a virtual function is called a polymorphic class.

所以原因是“因为标准是这么说的”。虽然这并没有真正告诉您为什么标准这么说,但我认为其他答案涵盖了这一点。

关于c++ - dynamic_cast 真的适用于多重继承吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7236417/

有关c++ - dynamic_cast 真的适用于多重继承吗?的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  4. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - "undefined method"用于 rails 模型 - 2

    我正在使用带有Rails的Devise,我想添加一个方法“getAllComments”,所以我这样写:classUser在我的Controller中:defdashboard@user=current_user@comments=@user.getAllComments();end当我访问我的url时,我得到了undefinedmethod`getAllComments'for#我做错了什么?谢谢 最佳答案 因为getAllComments是一个类方法,而您正试图将其作为实例方法访问。您要么需要访问它:User.getAllCom

  8. Ruby on Rails regexp equals-tilde 与 array include 用于检查选项列表 - 2

    我正在使用Rails3.2.3和Ruby1.9.3p0。我发现我经常需要确定某个字符串是否出现在选项列表中。看来我可以使用Ruby数组.includemethod:或正则表达式equals-tildematchshorthand用竖线分隔选项:就性能而言,一个比另一个好吗?还有更好的方法吗? 最佳答案 总结:Array#include?包含String元素,在接受和拒绝输入时均胜出,对于您的示例只有三个可接受的值。对于要检查的更大的集合,看起来Set#include?和String元素可能会获胜。如何测试我们应该根据经验对此进行测试

  9. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  10. ruby-on-rails - 我真的需要在 Rails 中使用 csv gem 吗? - 2

    我的问题很简单:我是否必须在使用RubyonRails的类上require'csv'?如果我打开一个railsconsole并尝试使用CSVgem它可以工作,但我必须在文件中这样做吗? 最佳答案 CSVlibrary是ruby​​标准库的一部分;它不是gem(即第三方库)。与所有标准库(与核心库不同)一样,csv不会由ruby​​解释器自动加载。所以是的,在您的应用程序中某处您确实需要要求它:irb(main):001:0>CSVNameError:uninitializedconstantCSVfrom(irb):1from/Us

随机推荐