определить strInterface в interface.h
// interface.h
#ifndef INTERFACE_H_
#define INTERFACE_H_
const char* strInterface = "the difference between char* and char array";
#endif
в классе OneUsing вызывается строка strInterface
// oneUsingInterface.h
#ifndef ONEUSINGINTERFACE_H_
#define ONEUSINGINTERFACE_H_
class OneUsing
{
private:
int mData;
public:
OneUsing();
OneUsing(int a);
void print();
};
#endif // ONEUSINGINTERFACE_H_
// oneUsingInterface.cpp
#include "oneUsingInterface.h"#include "interface.h"#include <iostream>
using namespace std;
OneUsing::OneUsing()
{}
OneUsing::OneUsing(int a)
{
mData = a;
}
void OneUsing::print()
{
cout<<"mData: "<<mData<<" strInterface: "<<strInterface<<endl;
}
в main.cpp interface.h включен, так как strInterface вызывается напрямую; он также включает oneUsingInterface.h, так как будет создан экземпляр OneUsing.
//main.cpp
#include <iostream>
#include "interface.h"#include "oneUsingInterface.h"
using namespace std;
int main()
{
cout<<strInterface<<endl;
OneUsing* pObject = new OneUsing(5);
pObject->print();
}
Теперь возникает вопрос:
g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra -c .//main.cpp
g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra -c .//oneUsingInterface.cpp
g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra main.o oneUsingInterface.o -o main
oneUsingInterface.o:(.data+0x0): multiple definition of `strInterface'
main.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
Однако, если strInterface определен так, проблем не возникает:
// interface.h
#ifndef INTERFACE_H_
#define INTERFACE_H_
const char strInterface[] = "the difference between char* and char array";
#endif
Могли бы некоторые ребята рассказать мне подробнее о разнице между char*
а также char[]
в этом случае?
PS: мы часто объявляем глобальную переменную с extern
Ключевое слово в заголовочном файле, и мы определяем его в чьем-то файле реализации.
Разница в том, что const char strInterface[]
определяет константу. Константы являются локальными для каждого файла, в который они включены. Вы получите отдельную копию в каждом файле.
Указатель const char* strInterface
указывает на постоянные данные, но сам указатель не является константой. Таким образом, по умолчанию это видно другим переводчикам.
Переменные в пространстве имен, которые объявлены const
иметь внутренняя связь по умолчанию, так что вы можете иметь такую переменную с одинаковым именем, определенную в нескольких единицах перевода, не вызывая ошибку ссылки.
Эта переменная не const
так будет внешняя связь Это означает, что в любой программе может существовать только одно такое определение:
const char* strInterface = "...";
const
версия будет:
const char* const strInterface = "...";
Это const
потому что нет разницы между константностью массива и константой его элементов. (IIRC имеет некоторую формальную двусмысленность в этом факте в стандарте.) Вы можете иметь одно такое определение на единицу перевода в программе.
const char strInterface[] = "...";
У вас есть два разных типа здесь:
Первый, const char* strInterface
является указателем на постоянный символ, и поэтому вы создаете указатель с одинаковым именем в глобальной области видимости в двух разных единицах компиляции, заставляя компоновщика жаловаться на это. Обратите внимание, что вы можете сделать указатель на что-то совершенно другое позже в коде. Сам указатель является изменяемым; строка, на которую он указывает, неизменна.
Во-вторых, const char strInterface[]
это массив константных символов, который создается локально для каждой единицы компиляции, поэтому компоновщик находит несколько определений этой строки, которые не конфликтуют. Эта константа неизменна.