Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Глюк линкеров C++

505
27 июня 2008 года
vAC
343 / / 28.02.2006
Наткнулся вот на такой фокус линкера...
Имеется три файла:
Файл 1:
 
Код:
int main()
{
 return 0;
}

Файл 2:
 
Код:
#include <iostream>
class Class {
public:
 Class() { std::cout << "Module1: Class::Class();" << std::endl; }
} c1;

Файл 3:
 
Код:
#include <iostream>
class Class {
public:
 Class() { std::cout << "Module2: Class::Class();" << std::endl; }
} c2;

Экземпляры c1 и с2 можно было бы создавать и внутри некоторой функции модуля и вызывать их из основного - от этого эффект не изменится.

А фокус заключается в том, что для обоих объектов c1 и c2 будет вызван один и тот же конструктор. У меня, например, такой вывод:
Module1: Class::Class();
Module1: Class::Class();
Я решил немного поэкспериментировать на двух компиляторах и вот что получилось:
MSVC 6.0,8.0:
Если один из конструкторов подставляемый (определенный с директивой inline или определен
в объявлении класса, как в примере), а другой нет, то выкидывается ошибка линковки.
Если же сделать все тоже самое, но для метода, то все в порядке.
gcc-3.3.3:
Отличий для конструктора и метода нет.
Программа не линкуется только тогда, когда оба конструктора или метода неподставляемые.

А теперь то, как этого можно избежать не изменяя имен классов.
Для этого применяем современную альтернативу static - namespace.
Объявления классов заносятся в анонимное пространство и спокойно используются внутри своей единицы трансляции.

Из этого можно сделать следующий вывод: объявляйте конструкции локального использования внутри анонимных
пространств имен, а внешние - в именных. Было бы не приятно, если подобного рода штука выскочила из-за совпадения
имени вашего класса с другим из сторонней библиотеки.
Файл 2:
 
Код:
#include <iostream>
namespace {
class Class {
public:
 Class() { std::cout << "Module1: Class::Class();" << std::endl; }
} c1;
} // namespace {

Файл 3:
 
Код:
#include <iostream>
namespace {
class Class {
public:
 Class() { std::cout << "Module2: Class::Class();" << std::endl; }
} c2;
} // namespace

Для работоспособности, конечно, достаточно определить одно пространство, но я такой методики стараюсь
придерживаться всегда. И благо, что я наткнулся на этот баг не в реальном проекте, а когда от безделья на работе игрался с компилятором.

Может кто-то пояснит механизм получения такого результата?
260
27 июня 2008 года
Ramon
1.1K / / 16.08.2003
Досели неизвестная проблема, приводящая к крушению мира и концу света.

А теперь представим идиотов, создающих оптимизирующий компилятор и линкер, производящие дохлый код.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог