2013-05-15 19 views
7

Kiedy mam dwie matryce przeciążeń funkcyjne tak:funkcja przeciążenia: const * vs const &

template<class T> 
void foo(T const&) 
{ 
    // do something with a const reference 
    cout << "const reference version"; 
} 

template<class T> 
void foo(T const*) 
{ 
    // do something with a const pointer 
    cout << "const pointer version"; 
} 

Dlaczego kompilator wybrać pierwszą wersję, gdy tworzony z const typ wskaźnika?

int* bar; 
foo(bar); // prints "const reference version" 

char const* baz; 
foo(baz); // prints "const pointer version" 
+2

Możesz znaleźć ładne wyjaśnienie tego problemu na kanale 9: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core -Cpp-3-of-n. Ale zasadniczo Mark B odpowiedział na twoje pytanie. – mkaes

Odpowiedz

4

Powodem jest fakt bar jest non-const wskaźnik, więc int* const& jest rzeczywiście lepszy mecz niż int const* ponieważ nie trzeba dodawać const do typu wskaźnika.

Jeśli bar został zakwalifikowany jako const, byłby to dokładny odpowiednik dla wersji T const*.

0

template<class T> void foo(T const*) wymaga wskaźnika const na T. Cóż, jeśli była to jedyna deklaracja, jaką masz, wystąpi błąd kompilacji, gdy próbujesz przekazać wskaźnik nie będący const.

Z template<class T> void foo(T const&) wywnioskowany typ T to int*, który jest podany w odniesieniu do funkcji.

2
#include <iostream> 
using namespace std; 
void foo(int const&) { 
    cout << "const reference" << endl; 
} 

void foo(int const*) { 
    cout << "const pointer" << endl; 
} 

int main() { 
    int *hi; 
    foo (hi); //const pointer 
    foo((*hi)); //const reference 
    foo(&(*hi));//const pointer 
} 

Umowa dotyczy referencji, a wskaźniki są różne. Wskaźnik jest unikatowym typem, gdzie jako odniesienie do wartości nie różni się od samej wartości, a raczej od aliasu do obiektu. Na przykład ta wersja powyższego kodu nie będzie się kompilować.

#include <iostream> 
using namespace std; 
void foo(int const&) { 
    cout << "const reference" << endl; 
} 

void foo(int) { 
    cout << "hi there" << endl; 
} 

int main() { 
    int hi; 
    foo(hi); //const reference 
} 

Ponieważ deklaracje foo są niejednoznaczne. Kompilator nie może decydować między nimi.

+0

dzięki za demonstrację dwuznaczności – idefixs

1

Możesz określić, co się dzieje z typami szablonów, używając typeid.

#include <iostream> 
#include <typeinfo> 
using namespace std; 

template<class T> void foo(T const&) { 
    cout << "const reference version T="<< typeid(T).name()<<endl; 
} 

template<class T> void foo(T const*) { 
    cout << "const pointer version T="<<typeid(T).name()<<endl; 
} 

int main() { 
    int* i_ptr=0; 
    foo(i_ptr); 

    const int* ci_ptr=0; 
    foo(ci_ptr);  
} 

This wyjścia (nota dokładny wynik zależy od kompilatora)

const reference version T=Pi 
const pointer version T=i 

co pokazuje, że w pierwszym przypadku T = int* oraz pełnego typu argument jest int* const&, aw drugim T=int i pełne typ argumentu to int const *.

Powiązane problemy