Задать вопрос
@dendibakh

Какой смысл внешней компоновки имени класса в C++?

Всем доброго времени суток!
Всегда писал так и не задумывался о компоновке имени класса:
C.h
----------
#pragma once
class w
{
public:
    w();
};


C.cpp
----------
#include "C.h"
w::w() {}


A.cpp
-----------
#include "C.h"


B.cpp
-----------
#include "C.h"

Согласно ответам здесь имя класса, объявленного в пространстве имен имеет внешнюю компоновку.
Так же это подтверждается цитатой из стандарта:
An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage.

Но у меня сразу возникает мысль. Если компоновка имени внешняя, то это значит, что это имя доступно в других единицах трансляции. Однако, как с функциями не работает:
foo.cpp
----------
void foo() {}


bar.cpp
----------
void foo();

void bar()
{
   foo();
}

То есть я не могу написать так:
A.cpp
----------
class A
{
};


B.cpp
----------
class A;

void foo(A a) // A is an incomplete type
{
}

Собственно вопрос возник, когда я начал получать падения тестов после добавления нового mock-класса с уже существующим именем, но в совершенно другой cpp-файл.
Вопрос: какой смысл тогда во внешней компоновке имени класса? Прошу экспертов С++ помочь разобраться.
  • Вопрос задан
  • 2472 просмотра
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Но у меня сразу возникает мысль. Если компоновка имени внешняя, то это значит, что это имя доступно в других единицах трансляции. Однако, как с функциями не работает:
foo.cpp
----------
void foo() {}


bar.cpp
----------
void foo();

void bar()
{
   foo();
}

Почему же? Работает.

То есть я не могу написать так:
A.cpp
----------
class A
{
};


B.cpp
----------
class A;

void foo(A a) // A is an incomplete type
{
}


Но этот пример не имеет никакого отношения к компоновке имени A. Вы не можете написать так, потому что операция передачи по значению недоступна для неполного типа. Но уже вот так вполне можно написать:

A.cpp
----------
class A
{
};


B.cpp
----------
class A;

void foo(A& a) // A is an incomplete type, but who cares
{
}


Вопрос: какой смысл тогда во внешней компоновке имени класса?

Смысл тот, что имя класса (полное, со всеми неймспейсами) обозначает единственную сущность во всех единицах трансляции одной программы.
Ответ написан
Комментировать
@dendibakh Автор вопроса
Здравствуйте!
Смысл тот, что имя класса (полное, со всеми неймспейсами) обозначает единственную сущность во всех единицах трансляции одной программы.

Да, я тоже думал, что это так. Но пример ниже отлично работает:
A.cpp
----------
struct A
{
   void foo() {}
};

void fooA()
{
   A a;
   a.foo();
}

B.cpp
----------
struct A
{
   void foo() {}
};

void fooB()
{
   A a;
   a.foo();
}


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

Почему же? Работает.

Это Вы имеете ввиду классический пример, когда мы включаем в cpp файлы только объявление класса?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы