2013-06-10 8 views
5

Ich habe den Code:Überlastung auf const und volatile - warum funktioniert es als Referenz?

#include "stdafx.h" 
#include <iostream> 

using namespace std; 


void func(const int& a) 
{ 
    std::cout << "func(const)" << std::endl; 
} 

void func(volatile int& a) 
{ 
    std::cout << "func(volatile)" << std::endl; 
} 

void func(const volatile int& a) 
{ 
    std::cout << "func(const volatile)" << std::endl; 
} 

int main() 
{ 
    const int a = 0; 
    const volatile int b = 0; 
    volatile int c = 0; 
    func(a); 
    func(b); 
    func(c); 
    system("pause"); 
    return 0; 
} 

Der obige Code basiert auf zeigt Überlastung, ob die Parameter const/volatil. Wenn ich jedoch die Parameter von int& zu int ändere, kompiliert der Code nicht mehr und ich kann nicht basierend auf konstanten/volatilen Parametertypen überladen. Ich verstehe nicht, warum wir auf der Basis von const und volatile überladen können, wenn der int als Verweis übergeben wird, aber nicht, wenn sein Wert überschritten wird?

EDIT Ich sollte betonen, ich verstehe, was eine Referenz tut - ich verstehe nicht, warum ein Verweis Alias ​​auf const überladen darf, aber eine normale int ist nicht.

Antwort

4

Vielleicht ist es sinnvoll, einen Schritt von den Funktionen zurückzutreten und sich die Use Cases anzusehen.

int  anInt  = 1; 
const int aConstInt = 1; 

Als nächstes werfen wir einen Blick auf das, was passiert, wenn diese Variablen mit den Werten anderer ganzen Zahlen gesetzt und konstant:

Zunächst werden wir eine ganze Zahl und eine konstante ganze Zahl für den Einsatz in unseren Beispielen definieren Zahlen:

int  a = anInt;  // This works, we can set an int's value 
         // using an int 
int  b = aConstInt; // This works, we can set an int's value 
         // using a const int 
const int c = anInt;  // This works, we can set a const int's value 
         // using an int 
const int d = aConstInt; // This works, we can set a const int's value 
         // using a const int 

Wie Sie sehen können, gibt es keine Möglichkeit zu lösen, die eine Funktion basierend auf wählen auf dem Verhalten (sowohl ein const int ein akzeptierte Überlastung durch int und eine const int werden kann und ebenfalls ein int kann sowohl von einem int als auch von einem const int akzeptiert werden).

Als nächstes werden wir einen Blick auf das, was passiert, wenn der erste Satz von Variablen Referenzen übergeben:

int& a = anInt;  // This works because we are using a 
        // non-constant reference to access a 
        // non-constant variable. 
int& b = aConstInt; // This will NOT work because we are 
        // trying to access a constant 
        // variable through a non-constant 
        // reference (i.e. we could 
        // potentially change a constant 
        // variable through the non-const 
        // reference). 

const int& c = anInt;  // This works because we are using a 
          // constant reference (i.e. "I cannot 
          // try to change the referenced 
          // variable using this reference") to 
          // a non-constant variable. 
const int& d = aConstInt; // This will work because we are trying 
          // to access a constant variable 
          // through a constant reference. 

Wie Sie sehen können, gibt es einige nützliche Verhalten, das zwischen einer hatte aus der Unterscheidung werden kann int reference und const int reference (dh die Erstellung einer nicht konstanten Referenz wird verhindert, wenn ein konstanter Referenztyp erwartet wird).

13

Das Problem ist, dass die oberste Ebene const und/oder volatile in Überladungsauflösung ignoriert werden. So

void foo(const int); 

ist genau die gleiche wie

void foo(int); 

und in ähnlicher Weise für volatile. Dies ist eine Sprachregel und macht Sinn, da die Argumente nach Wert übergeben werden. Andererseits hat der Verweis auf const/volatile oder Zeiger auf const/volatile eine andere Bedeutung: Sie dürfen nicht-konstante/flüchtige Methoden für das, worauf sie verweisen oder auf die sie verweisen, nicht aufrufen. Hier sind die constvolatile nicht oberste Ebene.

void foo(int& i);  // can modify what i refers to, and this has effects outside of foo. 
void foo(const int& i); // cannot modify what i refers to 

Die beiden oben genannten Erklärungen haben sehr unterschiedliche Semantik, also die Sprache, die Überladungsauflösung über sie verschieden macht.

+0

Könnten Sie näher auf den Unterschied zwischen int und int eingehen? Ich dachte, eine Referenz ist nur ein Alias ​​für eine andere Variable? So sind Int und Int nicht anders? Man meint nur den Alias? – user997112

+1

@ user997112 Wenn Sie Referenzen verwenden, wird keine Kopie erstellt. Wenn Sie Plain Pass-By-Value verwenden, wird das Argument kopiert. –

+0

@ user997112 Ich habe versucht zu erarbeiten.Im Referenzfall sind die Semantiken radikal verschieden. Es ist nützlich, wenn die Sprache separate Überladungen hat. Sie nicht zu haben, wäre verwirrend. – juanchopanza

Verwandte Themen