Как уже отмечали другие, вы не можете просто объявить их друзьями:
Car &operator+(const Car &c);
CarShop &operator+(const Car &c);
Даже если бы вы могли скомпилировать и связать его, это просто не сработало бы. И вы не можете связать, потому что они имеют одинаковые подписи (возвращаемый тип не включен в подпись). У вас есть два варианта: либо иметь друзей, не являющихся членами, либо иметь функции-члены (объявление друзей не требуется). Если вы хотите, чтобы у вас не было друзей, вы должны были объявить их так, указав оба операнда:
Car operator+(const Car &c1, const Car &c2);
CarShop operator+(const CarShop &cs, const Car &c);
Обратите внимание, что, как указал Джеймс, эти операторы не должны возвращать ссылки. Они возвращают новые экземпляры по определению.
Однако операторы друзей необходимы, только если первый параметр имеет тип, отличный от любого класса, который находится под вашим контролем. Например, было бы необходимо объявить оператор друга, если первый параметр имеет тип std :: string или int. Однако, поскольку это ваши классы, вам лучше объявить операторы как члены:
Car operator+(const Car &c2); // this is declared inside the Car class
CarShop operator+(const Car &c); // this is declared inside the CarShop class
Нет необходимости в друзьях здесь, поскольку они являются членами. Ну, строго говоря, вы можете объявить CarShop::operator+(const Car&)
своим другом в классе Car, если вы хотите получить доступ к личным членам Car. Но для Car::operator+(const Car&)
это абсолютно не нужно.