Что происходит с оператором ostream в объектном файле?
Я хотел бы понять, где оператор ostream класса "живет" в объектном файле. В приведенном ниже примере кода я разработал класс C++ DeltaTimer, который поддерживает оператор ostream. Далее ниже вывод "nm DeltaTimer.o". Подстановка для "ostream" в этих выходных данных показывает их для символа типа "U", то есть неопределенного. Но код компилируется (main.cpp включен для полноты) и связывается успешно, и выполняется как ожидалось, что означает, что ничто не является неопределенным. Но я не понимаю, к чему разрешает оператор ostream в выводе "nm", и был бы признателен, если кто-нибудь может посоветовать. Спасибо.
DeltaTimer.h:
#ifndef DeltaTimer_h
#define DeltaTimer_h
#include <iostream>
class DeltaTimer
{
public:
DeltaTimer();
virtual ~DeltaTimer();
void Foo();
private:
int m_foo;
friend std::ostream& operator<<(std::ostream& os, const DeltaTimer& rDeltaTimer);
};
#endif // DeltaTimer_h
DeltaTimer.cpp:
#include "DeltaTimer.h"
#include <iostream>
DeltaTimer::DeltaTimer() : m_foo(5)
{
std::cout << "DeltaTimer ctor" << std::endl;
}
DeltaTimer::~DeltaTimer()
{
std::cout << "DeltaTimer dtor" << std::endl;
}
void DeltaTimer::Foo()
{
std::cout << "DeltaTimer.m_foo == " << m_foo << std::endl;
}
std::ostream& operator<<(std::ostream& os, const DeltaTimer& rDeltaTimer)
{
os << "DeltaTimer[m_foo(" << rDeltaTimer.m_foo << ")]" << std::endl;
}
// This function is just a sanity-check for the output of "nm"
void Bar()
{
std::cout << "void Bar()" << std::endl;
}
main.cpp:
#include "DeltaTimer.h"
#include <iostream>
int main()
{
DeltaTimer deltaTimer;
std::cout << deltaTimer << std::endl;
}
Выход "нм":
>nm DeltaTimer.o
00000000000001a7 t _GLOBAL__I__ZN10DeltaTimerC2Ev
0000000000000145 T _Z3Barv
0000000000000167 t _Z41__static_initialization_and_destruction_0ii
00000000000000b0 T _ZN10DeltaTimer3FooEv
0000000000000000 T _ZN10DeltaTimerC1Ev
0000000000000000 T _ZN10DeltaTimerC2Ev
000000000000008a T _ZN10DeltaTimerD0Ev
0000000000000040 T _ZN10DeltaTimerD1Ev
0000000000000040 T _ZN10DeltaTimerD2Ev
U _ZNSolsEPFRSoS_E
U _ZNSolsEi
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
0000000000000000 V _ZTI10DeltaTimer
0000000000000000 V _ZTS10DeltaTimer
0000000000000000 V _ZTV10DeltaTimer
U _ZTVN10__cxxabiv117__class_type_infoE
U _ZdlPv
00000000000000f1 T _ZlsRSoRK10DeltaTimer
U __cxa_atexit
U __dso_handle
U __gxx_personality_v0
>nm DeltaTimer.o | grep -i ostream
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
1 ответ
Это потому что nm
показывает искалеченные имена. Чтобы напечатать читаемые человеком, вы хотите использовать --demangle
аргумент:
$ nm --demangle DeltaTimer.o
U __cxa_atexit
U __dso_handle
00000000000001a4 t _GLOBAL__sub_I__ZN10DeltaTimerC2Ev
U __gxx_personality_v0
0000000000000145 T Bar()
0000000000000167 t __static_initialization_and_destruction_0(int, int)
U operator delete(void*)
00000000000000f1 T operator<<(std::ostream&, DeltaTimer const&) // <== here's your guy!
00000000000000b0 T DeltaTimer::Foo()
0000000000000000 T DeltaTimer::DeltaTimer()
0000000000000000 T DeltaTimer::DeltaTimer()
000000000000008a T DeltaTimer::~DeltaTimer()
0000000000000040 T DeltaTimer::~DeltaTimer()
0000000000000040 T DeltaTimer::~DeltaTimer()
U std::ostream::operator<<(int)
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*)
0000000000000000 V typeinfo for DeltaTimer
0000000000000000 V typeinfo name for DeltaTimer
0000000000000000 V vtable for DeltaTimer
U vtable for __cxxabiv1::__class_type_info
Или просто использовать c++filt
для. В частности:
$ echo _ZlsRSoRK10DeltaTimer | c++filt
operator<<(std::basic_ostream<char, std::char_traits<char> >&, DeltaTimer const&)