I am having some problems with interfaces, inheritance and redefinition. In this case I am not sure why exactly C++ behaves like this, so if someone could explain and help me with this. I have this classes:
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;
}
};
mixer.h:
class mixer : public in_out {
public:
mixer(std::string name_)
: in_out(name_)
{}
~mixer() {}
};
So, if in my main file I have this:
int main(int argc, char *argv[])
{
prod prod1("prod1");
prod prod2("prod2");
mixer mixer1("mixer1");
mixer mixer2("mixer2");
prod1.bind(prod2);
return 0;
}
I get this error:
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
If I have this instead:
prod1.in_out::bind(prod2);
It works as expected.
What I do not understand is, shouldn't the compiler distinguish between these?
virtual module& bind(module &mod) = 0;
// and
virtual module& bind(mixer &mix) { return ((module&)mix); }
I guess the problem could be that both mixer
and prod
are child of module
(and in_out
). Maybe when the function bind
is called in main, it looks for it in the definition of prod
and only finds bind(mixer)
? What about bind(module)
? Is it private in that context?
What I would like to have is, no matter what I call prod.bind(prod)
or prod.bind(mixer)
, it distinguishes them at prod
's level, so I don't have to call .in_out
from there.
Thanks a lot :)
The problem is that when you defined class prod and declared function bind
virtual module& bind(mixer &mix);
in the class scope you hided all other functions with the same name of the base class. So then you called
prod1.bind(prod2);
the compiler sees only one candidate in the class scope: the function shown above. And it can not convert reference prod to reference mixer.
You should write in the class definition
using in_out::bind;
And as @Alex pointed out in his comment you have to make the destructor of class module virtual if you use polymorphism.
EDIT: If to substitute pfn_inout for in_out because there is no definition of pfn_inout then the following code is compiled successfuly
#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;
}