#include <iostream>
#include <vector>
#include <memory>
using namespace std;

class B; 
class C; 
class A {
public: 
    virtual void collide(shared_ptr<A> a) =0;  
    virtual void colisionwith(B&)=0; 
    virtual void colisionwith(C&)=0;
    virtual ~A() {}
};

class B : public A {
public:
    void collide(shared_ptr<A> a) override { a->colisionwith(*this);   } 
    void colisionwith(B&) override; 
    void colisionwith(C&) override;
};

class C : public A {
public:
    void collide(shared_ptr<A> a) override { a->colisionwith(*this);  } 
    void colisionwith(B&) override; 
    void colisionwith(C&) override;
};

void B::colisionwith(C&c) { cout <<"B "<<this<<" colides width a C "<< &c <<endl; }
void B::colisionwith(B&b) { cout <<"B "<<this<<" colides width another B "<< &b <<endl; }
void C::colisionwith(C&c) { cout <<"C "<<this<<" colides width another C "<< &c <<endl; }
void C::colisionwith(B&b) { cout <<"C "<<this<<" colides width a B "<< &b <<endl; }

int main() {
	vector<shared_ptr<A>> objects; 
	objects.push_back (make_shared<B>()); 
	objects.push_back (make_shared<B>()); 
	objects.push_back (make_shared<C>()); 
    for (int i = 0; i < objects.size(); i++)
    {
        for (int j=i+1; j < objects.size(); j++)
        {
        	objects[i]->collide(objects[j]);
         }
    }
return 0;
}