Suppose I have the following:
#include <iostream>
#include <string>
template<class T>
class base
{
public:
void print()
{
T t = get();
std::cout << t << std::endl;
}
virtual T get() const
{
// assumes T can be constructed from, say, -1
T t = -1.0;
return t;
}
};
class derived : public base<std::string>
{
public:
virtual std::string get() const
{
// this is a silly example, but one can
// imagine that what we return here could
// depend on data members of derived
return "this is a string";
}
};
int main()
{
derived d;
d.print();
return 0;
}
It seems to me that d.print() should call derived::get() because get() is virtual. However, I’m getting a compiler error saying that I can’t initialize a string to -1.0, which means that the compiler is trying to call base::get() when I call d.print(). What’s going on?
No, that compiler error means that the compiler is trying to instantiate
base<std::string>::get(), which it must do becausederivedusesbase<std::string>as a base class. Just because you don’t call a function doesn’t mean you can’t. You could still callbase<std::string>::get()directly.You instantiated
base<std::string>and used it as a base class. Sincebase<std::string>::get()is a virtual function, it is considered “used” by the fact that you usebase<std::string>as a base class. Since it is in use, it must be instantiated. So the compiler must and will attempt to compile the function.And since
std::stringcannot be implicitly constructed from a float, the compiler errors out from a failed template substitution.