Simple C++ Hash function library
Use the standard library

But I'd like to refine IDigest more elegantly. How can I do it?

Your IDigest basically reimplements std::vector&lt;uint8_t&gt;. Realizing this, I would therefore remove it entirely and replace it with std::vector&lt;uint8_t&gt;. You could add this to namespace chash if you like:
using Digest = std::vector&lt;uint8_t&gt;;

Your IDigest has limitations: you cannot compare two digests with each other. But you can with std::vector&lt;uint8_t&gt;. The only feature your class has is that it has a function to convert it to a string containing hexadecimal characters. I would leave that out entirely, and leave it up to the application to implement whatever they need to convert a digest to some other form, if they need that at all. But if you do want to provide this as a utility, simply create an out-of-class function to do this:
std::string toHex(const Digest &amp;digest) {
    std::string outHex;
    outHex.reserve(digest.size() * 2);

    for (auto b: digest) {
        ...
    }

    return outHex;
}

Consider whether you need virtual base classes
Do you really need virtual base classes? These come with a cost: derived classes will now have a vtable, and function calls need to go through an extra level of indirection. Consider using a non-virtual base class, and make the base class's constructor protected, so you can no longer create an instance of a base class.