Q<B> and Q<A> are unrelated classes. Imagine that you are the client of B calling test() : what do you assign to the result if you do not know what type it will have?
The fact that both Q<A> and Q<B> are instances of the same class template does not alter the fact that they are two completely unrelated classes, possibly with a completely different layout (due to specialized specialization).
This will not be different from this:
struct X { virtual std::string test() = 0; }; struct Y : X { virtual int test() { return 42; }
The client calling test() with a pointer to X expects the result to be string , but the "Whoops!" Object that this pointer points to is of type Y , and return type Y::test() is int . What is going to happen? Error at runtime?
Y y; X* p = &y; std::string s = p->test();
C ++ is a statically typed language, which means that type checking is done at compile time. In this case, a message from the compiler should tell you that the derived class does not adhere to the interface of the class from which it comes.
If you're curious about what the “invalid covariant return type” means and, in particular, the word “covariant”, this is easily explained.
Suppose you have a base class B with a virtual function foo() that returns X* :
struct B { virtual X* foo(); };
And suppose you have a class D derived from B that overrides foo() , returning Y* , where Y is the class derived from X :
struct D : B { virtual Y* foo(); };
This is problem? Well, the correct answer comes from answering this slightly better question: "Will this be a problem for a client calling foo() who is expecting X* return?"
And the answer to this question is obviously No, since Y is a derived class of X , so you can return a pointer to Y instead of a pointer to X :
D d; B* b = &d; X* p = b->foo();
This is an example of a covariant return type. In your example, the return type C::test() not covariant with respect to the return type B::test() .