Mangling

Visual C++ name mangling Archive du 06/07/2019 le 30/10/2019

Calling conventions Archive du 15/08/2019 le 30/10/2019

Microsoft C++ Name Mangling Scheme Archive du 20/07/2006 le 30/10/2019

External functions with the __declspec(dllimport) attribute have prefix __imp_ in all compilers except Borland.

C++ Name Mangling/Demangling Archive du 30/04/2002 le 30/10/2019

https://d.fuqu.jp/c++filtjs/

https://demangler.com

Les méthodes définies dans un entête ont un attribut weak

Le corps d'une méthode template doit être identique quelque soit le fichier objet généré. Les méthodes template étant compilés dans chaque fichier objet (possibilité de nombreux doublons), le compilateur va leur donner l'attribut weak.

Si l'implémentation n'est toujours identique, le compilateur va en prendre une au hasard et la généraliser.

cpp/linker/weak/Entete.h
#pragma once
 
#include <iostream>
 
class Entete
{
 public:
  static void go()
  {
#ifdef HACK
    std::cout << "A" << std::endl;
#else
    std::cout << "B" << std::endl;
#endif
  }
};
cpp/linker/weak/ClasseA.h
#pragma once
 
class A
{
 public:
  static void go();
};
cpp/linker/weak/ClasseB.h
#pragma once
 
class B
{
 public:
  static void go();
};
cpp/linker/weak/ClasseA.cpp
#define HACK
 
#include "ClasseA.h"
#include "Entete.h"
 
void A::go() { Entete::go(); }
cpp/linker/weak/ClasseB.cpp
#undef HACK
 
#include "ClasseB.h"
#include "Entete.h"
 
void B::go() { Entete::go(); }
cpp/linker/weak/main.cpp
#include "ClasseA.h"
#include "ClasseB.h"
 
int main()
{
  A::go();
  B::go();
}
cpp/linker/weak/ClasseA.cpp.nm
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
000000000000005d t _GLOBAL__sub_I__ZN1A2goEv
0000000000000010 t __static_initialization_and_destruction_0(int, int)
0000000000000000 T A::go()
0000000000000000 W Entete::go()
                 U std::ostream::operator<<(std::ostream& (*)(std::ostream&))
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cout
                 U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
0000000000000000 r std::piecewise_construct
0000000000000000 b std::__ioinit
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
cpp/linker/weak/ClasseB.cpp.nm
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
000000000000005d t _GLOBAL__sub_I__ZN1B2goEv
0000000000000010 t __static_initialization_and_destruction_0(int, int)
0000000000000000 T B::go()
0000000000000000 W Entete::go()
                 U std::ostream::operator<<(std::ostream& (*)(std::ostream&))
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cout
                 U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
0000000000000000 r std::piecewise_construct
0000000000000000 b std::__ioinit
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)

On voit que le symbole Entete::go() est défini deux fois avec l'attribut weak. Mais le #define étant différent, les deux implémentations sont différentes.