C++:继承函数并重新定义它们

C++: inheriting functions and redefining them

本文关键字:定义 新定义 继承 函数 C++      更新时间:2023-10-16

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

module.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;
}
};

prod.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;
}
};

混合器.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)的子代。也许当函数bind在main中被调用时,它在prod的定义中查找它,但只找到bind(mixer)bind(module)呢?在这种情况下它是私人的吗?

我想要的是,无论我称之为prod.bind(prod)还是prod.bind(mixer),它都在prod的级别上区分它们,所以我不必从那里调用.in_out

非常感谢:)

问题是,当您定义类prod并声明函数绑定时

virtual module& bind(mixer &mix);

在类作用域中,隐藏了与基类同名的所有其他函数。所以你打电话给

prod1.bind(prod2);

编译器在类作用域中只看到一个候选者:上面显示的函数。并且它不能将参考脉冲转换为参考混频器。

你应该写在类定义

using in_out::bind;

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

编辑:如果因为没有pfn_inout的定义而用pfn_inoout代替in_out,则以下代码已成功编译

#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;
} 

在C++中,名称查找在找到名称的范围内停止。(有一些例外,与ADL有关,但它们不适用此处。)这样做的原因是为了避免更改语义的派生if函数班

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

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;
}
};

派生类将实现它们自己的CCD_ 13版本,但没有别的。

不过有一件事。上下文中的转换(Module&)mix在编译器看不到CCD_ 15的完整定义的情况下,是reinterpret_cast,几乎可以肯定不是什么你想要的。我在示例中使用了static_cast,以与你已经做了什么,但事实上,如果编译器看不到CCD_ 18的定义。在这种特殊情况下,事实上,第二个bind根本不需要由于CCD_ 20将隐式转换为CCD_,而不需要您进行转换。(但它相当这段代码可能只是一个非常简单的例子在你的真实代码中,你实际上在做更多的事情复杂。)