2013-12-22 20 views
1

У меня возникают ошибки multiple defintion of Math без файла для дела из следующего кода:экземпляр объекта из класса в заголовке

#ifndef SOMEMATH_H 
#define SOMEMATH_H 

class math{ 
public: 
    int add(int a, int b); 
    int divide(int a, int b); 
    int subtract(int a, int b); 
    int multiply(int a, int b); 
}Math; 

#endif // SOMEMATH_H 

изменяющегося Math любого другого имя не изменяет проблему. Создание экземпляра математического объекта другим способом не устраняет проблему. Не создавая объект из math в файлах заголовков, проблем не возникает, но мне нужен класс, созданный в заголовке. Это возможно?

ответ

2

Ваш заголовок определяет экземпляр class math, названный Math, что является плохой идеей, поскольку оно вызывает именно проблему, с которой вы столкнулись: если два файла включают заголовок, вы получаете два экземпляра с тем же именем.

Вы не можете безопасно создать экземпляр класса в заголовке, подобном этому. Вы можете объявить, что он существует, и поместить фактическое определение в исходный файл .cpp.

Этот конкретный класс выглядит так, как будто он имеет только методы и никаких фактических данных, связанных с ним. Это заставляет меня задаться вопросом, что вы на самом деле пытаетесь сделать.Если вы просто пакетирования вверх набор функций под одним именем, вы могли бы рассмотреть namespace вместо этого, или по крайней мере сделать функций static методов в рамках класса:

class Math { 
public: 
    static int add(int a, int b); 
    static int divide(int a, int b); 
    static int subtract(int a, int b); 
    static int multiply(int a, int b); 
}; 

или:

namespace Math 
{ 
    int add(int a, int b); 
    int divide(int a, int b); 
    int subtract(int a, int b); 
    int multiply(int a, int b); 
} 

Любой из этих вариантов избавит вас от необходимости использования экземпляра класса для доступа к функциям. Вы можете обратиться к этим функциям как Math::add(), Math::divide() и т. Д.

2

Короткий ответ: нет экземпляра в заголовке.

Долгий ответ: каждый cpp, в который ваш файл прямо или косвенно включен, будет иметь объект Math, и компоновщик будет жаловаться, потому что он не сможет выбрать только один.

Немного больше об этом здесь, http://csapp.cs.cmu.edu/public/ch7-preview.pdf, охватывающих unix-компоновщик, но идея останется прежней. В основном ваш пример не будет работать на:

Правило 1: Несколько сильных символов не допускается

Честно говоря, я думаю (но не уверен), что компоновщик может, в большинстве случаев, решить, что вы создаете ссылку на символ в большинстве случаев и берете одно из «.o» в качестве реального объекта. Но только для 1 библиотеки, и, следовательно, ошибка будет расти, как только у вас будет несколько DLL. Так что это не стоит боль.

Таким образом, общее правило - «нет экземпляра в заголовке». Если вы хотите глобальную переменную:

  • Мгновенное действие math Math в одном cpp (даже если вы хотите).
  • Используйте «внешнюю математическую математику» в других файлах, используя ее.

Но если можно, избегайте глобальных объектов.

1
// .hpp 
#ifndef SOMEMATH_H 
#define SOMEMATH_H 

class math{ 
public: 
    int add(int a, int b); 
    int divide(int a, int b); 
    int subtract(int a, int b); 
    int multiply(int a, int b); 
}; 

extern math Math; 

#endif // SOMEMATH_H 

// .cpp 

math Math; 

но похоже, что вы пытаетесь имитировать математический класс Java. Просто используйте пространство имен.

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