Как разрешается конфликт этих имен в C ++? - PullRequest
3 голосов
/ 14 июня 2011

Скажите, у меня есть эта физическая структура:

/
  +-- conflicttest
  |     +-- A.cpp
  |     +-- A.h
  |     +-- main.cpp
  +-- libconflict
  |     +-- conflict
  |     |     +-- A.h
  |     |     +-- B.h
  |     +-- A.cpp
  |     +-- B.cpp

Это источники libconflict, сделайте глубокий вдох:

class B заголовок в libconflict:

// libconflict B.h
class B
{
public:
    void bar();
protected:
    int j_;
};

class B реализация в libconflict:

// libconflict B.cpp
#include "conflict/B.h"

void B::bar()
{
    std::cout << "B::bar" << std::endl;
}

class A заголовок в libconflict:

// libconflict A.h
# include "conflict/B.h"

class A : public B
{
public:
    A();
private:
    int i_;
};

class A реализация в libconflict:

#include "conflict/A.h"

A::A()
{
    std::cout << "libconflict A is alive" << std::endl;
    i_ = 51; // some random fields and values... I should admit I am lost
    j_ = 47;
}

Теперь источники конфликта испытаний почти закончились: заголовок

class A в конфликте:

// conflicttest A.h
class A
{
public:
    A();
    void foo();
};

class A реализация в конфликте:

// conflicttest A.cpp
#include "A.h"

A::A()
{
    std::cout << "A is alive" << std::endl;
}

void A::foo()
{
    std::cout << "A::foo" << std::endl;
}

инаконец, main.cpp:

// main.cpp in conflicttest
#include "conflict/A.h"

int main()
{
    B* b = new A;
    b->bar();
return 0;
}

Фу ... Я использую Visual Studio 2010 для создания этого решения.conflicttest - это исполняемый файл, который связан со статической библиотекой libconflict.Это компилируется как талисман, но, хотите верьте, хотите нет, на выходе получается:

A is alive
B::bar

Компоновщик на самом деле использует символ A из conflicttest, который абсолютно не является B и хуже,он может вызвать B::bar().

Я заблудился, почему компилятор не жалуется?

Ответы [ 4 ]

6 голосов
/ 14 июня 2011

Вы нарушили правило One Definition .

Компилятор не жаловался, поскольку он ограничен в том, что он может обнаружить при пересечении границ единицы перевода.

1 голос
/ 14 июня 2011

У вас есть два разных определения класса А. Это нарушение ODR. Таким образом, программа не является допустимой программой на C ++. Компиляторы не обязаны диагностировать эту ошибку.

1 голос
/ 14 июня 2011

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

1 голос
/ 14 июня 2011

Полагаю, вы на самом деле не связываете свою конфликтную жизнь Но на самом деле, просто не делай этого. Если вы абсолютно ДОЛЖНЫ, используйте пространства имен.

...