【问题标题】:C++: inheriting functions and redefining themC++:继承函数并重新定义它们
【发布时间】:2014-02-21 11:38:24
【问题描述】:

我在接口、继承和重新定义方面遇到了一些问题。在这种情况下,我不确定为什么 C++ 的行为是这样的,所以如果有人可以解释并帮助我解决这个问题。我有这个课程:

模块.h:

class mixer;

class module {

public:

  module(std::string name_) : name(name_) {}
  ~module() {}

  virtual module& bind(module &mod) = 0;
  virtual module& bind(mixer &mix) { return ((module&)mix); }

  std::string get_name() 
  {
    return name;
  }

  std::string name;
};

in_out.h:

class in_out : public module {

public:

  in_out(std::string name_) : module(name_) {}
  ~in_out() {}

  virtual module& bind(module &mod)
  {
    std::cout << "bind in_out in " << mod.name << std::endl;
    return mod;
  }

};

产品.h:

class prod : public in_out {

public:

  prod(std::string name_)
    : in_out(name_)
  {}

  ~prod() {}

  virtual module& bind(mixer &mix)
  {
    std::cout << "bind mixer in " << get_name() << std::endl;
    return mix;
  }

};

mixer.h:

class mixer : public in_out {

public:

  mixer(std::string name_)
    : in_out(name_)
  {}

  ~mixer() {}
};

所以,如果在我的主文件中有这个:

int main(int argc, char *argv[])
{
  prod  prod1("prod1");
  prod  prod2("prod2");
  mixer mixer1("mixer1");
  mixer mixer2("mixer2");

  prod1.bind(prod2);

  return 0;
}

我收到此错误:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:12:19: error: no matching function for call to ‘prod::bind(prod&)’
main.cpp:12:19: note: candidate is:
prod.h:19:23: note: virtual pfn_module& prod::bind(mixer&)
prod.h:19:23: note:   no known conversion for argument 1 from ‘prod’ to ‘mixer&’
make: *** [main] Error 1

如果我有这个:

prod1.in_out::bind(prod2);

它按预期工作。

我不明白的是,编译器不应该区分这些吗?

virtual module& bind(module &mod) = 0;
// and
virtual module& bind(mixer &mix) { return ((module&)mix); }

我猜这个问题可能是mixerprod 都是module(和in_out)的孩子。可能在main中调用函数bind时,在prod的定义中查找,只找到bind(mixer)bind(module) 呢?在那种情况下它是私有的吗?

我想要的是,无论我叫什么prod.bind(prod)prod.bind(mixer),它都以prod 的级别区分它们,所以我不必从那里调用.in_out

非常感谢:)

【问题讨论】:

    标签: c++ function inheritance parent-child virtual


    【解决方案1】:

    问题是当你定义类 prod 并声明函数 bind 时

    virtual module& bind(mixer &mix);
    

    在类范围内,您隐藏了与基类同名的所有其他函数。那么你打电话给

    prod1.bind(prod2);
    

    编译器在类范围内只看到一个候选者:上面显示的函数。并且它不能将参考产品转换为参考混合器。

    你应该写在类定义中

    using in_out::bind;
    

    正如 @Alex 在他的评论中指出的那样,如果您使用多态性,则必须将类模块的析构函数设为虚拟。

    编辑:如果用 pfn_inout 代替 in_out 因为没有定义 pfn_inout 那么下面的代码编译成功

    #include <iostream>
    #include <string>
    
    class mixer;
    
    class module {
    
    public:
    
      module(std::string name_) : name(name_) {}
      ~module() {}
    
      virtual module& bind(module &mod) = 0;
      virtual module& bind(mixer &mix) { return ((module&)mix); }
    
      std::string get_name() 
      {
        return name;
      }
    
      std::string name;
    };
    
    class in_out : public module {
    
    public:
    
      in_out(std::string name_) : module(name_) {}
      ~in_out() {}
    
      virtual module& bind(module &mod)
      {
        std::cout << "bind in_out in " << mod.name << std::endl;
        return mod;
      }
    
    };
    
    class mixer : public in_out {
    
    public:
    
      mixer(std::string name_)
        : in_out(name_)
      {}
    
      ~mixer() {}
    };
    
    class prod : public in_out {
    
    public:
        using in_out::bind;
    
      prod(std::string name_)
        : in_out(name_)
      {}
    
      ~prod() {}
    
      virtual module& bind(mixer &mix)
      {
        std::cout << "bind mixer in " << get_name() << std::endl;
        return mix;
      }
    
    };
    
    
    int main() 
    {
      prod  prod1("prod1");
      prod  prod2("prod2");
      mixer mixer1("mixer1");
      mixer mixer2("mixer2");
    
      prod1.bind(prod2);
    
        return 0;
    } 
    

    【讨论】:

    • 还将基类的析构函数设为虚拟。
    • 好的。很有意义 :) 但我收到了这个错误:error: ‘virtual module&amp; in_out::bind(module&amp;)’ is inaccessible
    • @makeMonday 我不知道您的示例中的 pfn_inout 是什么。我认为是 in_out。如果是这样,那么您的示例 main 仅包含这三个语句 prod prod1("prod1");产品 prod2("prod2"); prod1.bind(prod2);编译成功。
    • 是的,这是原来的名字,我改了一个更简单的名字,但在这个问题中是一个错字。无论如何,我遇到了一些链接问题。现在工作正常!谢谢:)
    【解决方案2】:

    在 C++ 中,名称查找在找到名称的范围内停止。 (有一些例外,与 ADL 相关联,但它们不适用 这里。)这样做的原因是为了避免改变语义 如果将名称添加到基中,则派生中的函数 类。

    通常,这应该不是问题,因为您应该 在一个接口中实现所有的虚函数 派生类。以及虚函数和非虚函数 函数不应该共享名称。在你的情况下,你 可能想要在基类中是这样的:

    class Module
    {
    private:
        virtual Module& doBind( Module& mod ) = 0;
    
    public
        Module& bind( Module& mod )
        {
            //  pre-conditions
            Module& results = doBind( mod );
            //  post-conditions and invariants
            return results;
        }
        Module& bind( Mixer& mix )
        {
            //  pre-conditions
            Module& results = doBind( static_cast<Module&>( mod) );
            //  post-conditions and invariants
            return results;
        }
    };
    

    派生类将实现自己的doBind 版本, 但没有别的。

    不过,有一件事。转换(Module&amp;)mix,在上下文中 编译器看不到Module的完整定义, 是reinterpret_cast,几乎可以肯定不是什么 你要。我在示例中使用了static_cast,以与 你做了什么,但事实上,如果编译器是非法的 看不到Module 的定义。在这种特殊情况下, 事实上,第二个 bind 函数,因为Mixer&amp; 将隐式转换为Module&amp;, 无需您进行转换。 (但是很 可能此代码只是一个非常简化的示例,并且 在您的真实代码中,您实际上正在做更多的事情 复杂。)

    【讨论】:

      猜你喜欢
      • 2014-03-31
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2013-11-30
      • 1970-01-01
      • 2020-02-06
      相关资源
      最近更新 更多