【问题标题】:Get function won't work on virtual method获取函数不适用于虚方法
【发布时间】:2019-04-05 21:58:14
【问题描述】:

对不起,如果这是一个愚蠢的问题,但我正在尽我最大的努力学习 cpp..

所以我正在上课练习,我对这段代码持怀疑态度,这里让我告诉你

class C {
     private:
         //pv
     protected:
         //pt
     public:
         //constructors etc.

         virtual ostream& print(ostream&, const C&) const;
};

Class D: public C {
      private:
         int b;
      public:
         //constructors etc.
         int get_b() const {return b;}

         virtual ostream& print(ostream&, const C&) const;
};

假设我想打印班级的成员变量,我可以(应该?)使用 get 函数,对吗?但我的问题是,当我调用虚函数并尝试打印成员变量时

//in cpp

ostream& operator<<(ostream& os, const D& d) {

    d.print(os);
    return os;
}
ostream& D::print(ostream& os, const C& c) const {

    os<<(C&)c;
    os<<c.get_b();
    return os;
}

这是问题所在,上面写着[Error] 'const class C' has no member named 'get_a',这绝对是真的,但是我如何使用需要获取/设置层次结构中其他类的虚函数呢?根据定义,D 应该继承除一些之外的所有公共方法,这意味着 get/set 函数也应该是 D 的函数,对吧?对不起,如果我太长了!

【问题讨论】:

  • D 继承了 C 的所有(公共和受保护)成员,因此您可以从 D 的实例调用在 C 中定义的方法。但您正试图做相反的事情,即调用一个方法从 C 的实例在 D 中定义。
  • @Steve 你是对的!但这不是意味着要修改虚拟吗?因为我宣布它为 ostream& D::print(ostream& os, const C& c) const;从 C 的实例调用 D 中定义的方法只是意味着更改参数,不是吗?
  • 我试过做:os
  • @Dave2222 1) 问题与print 方法无关。该错误指出class C 没有名为get_a 的方法。确实,您的class C 没有这样的方法。再看一遍,您的示例中没有任何类具有这种方法(应该是get_b?),因此您的代码与您的错误不匹配。 2)“我试过做:os” 举个例子:我怀疑它,因为get_b不是静态方法.
  • 为什么print 得到第二个参数而不是使用this

标签: c++ class get virtual


【解决方案1】:

如果 c 是 C,则不能调用 c.get_b(),因为 C 中没有这样的函数,并且 C 也不是从定义了 get_b() 的类派生的。

我会在 C 类中创建一个虚拟函数 get_b()。

PS:我想你的意思是 get_b 而不是 get_a。

【讨论】:

    【解决方案2】:

    您的代码中有几个问题。首先,您的一些功能是const 而不是其他功能。如果它们应该是“相同”的虚函数,那么它们必须匹配。

    那么显而易见的问题是:为什么要在顶部传递C?你已经有this

    virtual ostream& operator<<(ostream& os, const C& c) const {
        c.print(os);
        return os;
    }
    
    ostream& D::print(ostream& os) const override {
        os<<this->get_b();
        return os;
    }
    

    如果您有 C 的实例或派生版本,这将作为 DC 并且将调用覆盖的 print

    【讨论】:

      【解决方案3】:

      我建议以下策略。

      1. 使用virtual 成员函数允许C 类型的对象(及其派生类型)将特定类型的数据写入std::ostream

        virtual std::ostream& write(std::ostream& out) const;
        
      2. 使用非成员函数允许您使用&lt;&lt; 运算符使用基类的任何派生对象。可以使用virtual成员函数来实现。

        std::ostream& operator<<(std::ostream& out, C const& c)
        {
           return c.write(out);
        }
        

      virtual 成员函数的示例实现:

      class C {
      
         public:
      
            virtual std::ostream& write(ostream& out) const
            {
               // Write data specific to this class
               // ...
      
               return out;
            }
      };
      
      class D: public C {
      
         private:
      
            int b;
      
         public:
      
            virtual std::ostream& write(ostream& out) const
            {
               // Call the base class to do its job first.
               C::write(out);
      
               // Write data specific to this class
               out << b;
      
               return out;
            }
      };
      

      此策略可确保驻留在类继承层次结构中特定级别的所有数据仅在该级别处理。基类不需要知道派生类做什么,派生类也不关心基类如何做。

      现在,您可以使用:

      D d{...};
      std::cout << d << std::endl;
      

      【讨论】:

        猜你喜欢
        • 2021-10-11
        • 2014-10-17
        • 1970-01-01
        • 2013-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多