2

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

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

header.h

const QString reviewToString(const int); //Declaration - do I even need it now? 
const QString statusToString(const int); //Declaration - do I even need it now? 

const QString reviewToString(const int r) //Definition 
{ 
    switch(r) 
    { 
    case 0: 
     return "Excellent"; 
    case 1: 
     return "Great"; 
    case 2: 
     return "Okay"; 
    case 3: 
     return "Poor"; 
    case 4: 
     return "Terrible"; 
    default: 
     return "Unknown"; 
    } 
} 

const QString statusToString(const int s) //Definition 
{ 
    switch(s) 
    { 
    case 0: 
     return "Watched"; 
    case 1: 
     return "Bought"; 
    default: 
     return "Not Watched"; 
    } 
} 

Это выдержка из моего headerfile. У меня есть другие enum s и struct s, но они не так важны для этих функций, потому что они просто переводят целое число в QString, которое будет отображаться где-то в другом месте. У меня также есть охранник.

Теперь я получаю тонны ошибок, как это:

множественное определение `reviewToString (межд)»

Почему? Почему я не могу просто объявить и/или определить их в этом заголовке?

+3

Короткий ответ: используйте 'inline'. – deepmax

+0

@MM. хорошо, что это умно! Спасибо .. – Davlog

+0

BTW: Не указывайте тип возврата как 'const', пожалуйста. Он не имеет никакой реальной выгоды для реализации вами функции, и вызывающий может чувствовать себя оскорбленным, поскольку вы убираете некоторую свободу в том, что делать с объектом. Не берите в голову, что некоторые случаи, вызывающие накладные расходы ... –

ответ

4

Вам необходимо добавить inline к определению. Без этого каждая единица перевода создаст свою собственную копию, и компоновщик не будет знать, что они должны быть дублирующими и что ему разрешено выбрасывать все, кроме одной из этих копий.

Еще лучше, не добавляйте определение в заголовок, просто объявления достаточно. Переместите реализацию в свою собственную единицу перевода (.cpp-файл). Вам не нужен inline, и он имеет несколько преимуществ, которые становятся все более важными по мере роста вашего проекта.

+0

Знаете ли вы, почему охранники не защищают от этого? – jmstoker

+0

@jmstoker Это просто: они работают на единицу перевода. Они гарантируют, что каждая единица перевода содержит только одну копию, которая хороша, но не помогает бедному компоновщику, когда вы бросаете в него несколько единиц перевода. «Inline» изменяет тип экспортируемого символа, чтобы помочь компоновщику справиться с ним, в то время как защитник включения является частью препроцессора и давно ушел при вызове компоновщика. –

2

Проблема здесь One Definition Rule. (C++ Standard §3.2)

В принципе, вы не можете иметь несколько определений для функции во всей программе. Однако вы можете выполнять функции inline (в противном случае вам придется поместить их в файл .cpp).

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