2011-01-30 3 views
0

Прежде всего, спасибо за ваши подсказки.C++: проблема при перегрузке одного и того же оператора в двух разных классах

У меня возникли проблемы при попытке выполнить задание. Я уверен, что что-то не так с пространствами имен, включает в себя файлы заголовков и все это, но не знаю, что происходит.

Дело в том, что мне нужны два разных класса (допустим, Car и CarShop), каждый из которых должен перегрузить оператор +.

  • Car ->Car &operator+(const Car &c) (должен "добавить" две машины)
  • CarShop ->CarShop &operator+(const Car &c) (должен "добавить" машину к существующему CarShop)

В файле CarShop.h, мне нужно #include "car.h", так как он много работает с различными «автомобильными» объектами. Более того, в моем основном тестовом классе, скажем, main.cpp, мне также нужно #include "car.h" и #include "carshop.h".

Здесь я получаю сообщение об ошибке. Visual Studio (мы работаем с ней как с нашей IDE) дает мне «LNK1169 & LNK2005» ошибки, объясняя, что «один или несколько символов определены одновременно».

Кто-нибудь может мне помочь? Что мне делать, чтобы избежать конфликта между двумя перегруженными операторами?

PS. Оба из них (2 перегруженных оператора) объявляются как функции друзей для своих классов (в файлах .h) и реализованы в их соответствующем файле .cpp.

+4

(1) Пожалуйста, внесите ваш код; не видя кода, вызывающего ошибки, ошибки трудно диагностировать. (2) Что значит «добавить две машины»? (3) Ваш 'operator +' должен возвращать по значению, а не по ссылке, если он следует за поведением встроенного '+': он не должен мутировать ни один из его операндов и должен возвращать новый объект. Если вы хотите изменить один из операндов, вам следует использовать 'operator + ='. –

+1

У ваших файлов .h есть '# define' охранники? – Richard

+1

В вашем вопросе есть несогласованность: объявления функций, которые вы показываете, предназначены для перегрузки операторов-членов, но тогда вы говорите, что перегрузки «объявляются как функции друзей». Что он? –

ответ

2

Как уже отмечалось, вы не можете просто объявить их как друзей:

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&) это абсолютно не нужно.

1

Вы умножаете объявление типа автомобиля. В вашем main.cpp вы включаете car.h и carshop.h, а carshop.h уже включает в себя car.h. Без включения охранников это приводит к ошибкам компоновщика.

У вас есть две возможности:

  • удалить #include "Car.h" из вашего использования main.cpp
  • включают охрану, как это:

anyfile.h:

#pragma once 

/* ... the rest of your code ... */ 

В авось ваш компилятор не поддерживает #pragma once директива вы всегда можете использовать стандарт, хоть немного громоздким, макро охранниками в заголовки:

myheader.h:

#ifndef MYHEADER_H 
#define MYHEADER_H 

/* ... your code here ... */ 

#endif 
+1

Сообщение об ошибке, похоже, указывает на ошибку связи, поэтому он, вероятно, уже делает это. – fbafelipe

1

Короткий ответ: Не объявлять эти операторы в качестве друга.

Длинный ответ: Когда функция объявлена ​​как друг, это означает, что она не принадлежит классу, где она «объявлена» (фактически, вы не объявляете там функцию), вы просто говорите, что функция (обратите внимание, что это будет функция C, а не функция-член) является другом этого класса и может получить доступ к личным данным.

Возможно, вы используете друга, потому что видели код, используя код для оператора < < (с std :: ostream), но это не может быть членом, потому что вам нужно будет быть членом функции std :: ostream. Удалив друга, вы сделаете «это» первым оператором.

Смежные вопросы