In this specific example, I would have added a protected method:
protected:
virtual int getKickassNess() = 0;
// Bullet:
int getKickassNess() override { return 10; }
// Rocket:
int getKickassNess() override { return 9001; } // over 9000!
void Bullet::OnCollision(Projectile& other)
{
if (other.getKickassNess() > this->getKickassNess())
// wimp out and die
}
IMO Bullet and Rocket should not know that each other exist. Putting in these kinds of knows-about relationships often make things difficult, and in this specific case I can imagine it causing messy cyclic include issues.