Wysyłanie argumentu przez wskaźnik a przeładowanie nazwy funkcji

Odpowiedz Nowy wątek
2011-08-24 19:46
0

Cześć,

Mam pewien problem z interpretacją tego, co jest napisane w symfonii C++. Mam dajmy na to taki program:

#include <iostream>
using namespace std;
double funkcja1(const double *obiekt);
double funkcja2(double *obiekt);
int main() {
    double zmienna = 4.0;
    const double stala = 3;
    cout << funkcja1(&zmienna) << endl;
    cout << funkcja2(&zmienna) << endl;
    //cout << funkcja2(&stala) << endl; // Co oczywiste, tak nie można
    return 0;
}
double funkcja1(const double *obiekt)
{
    //*obiekt += 1; // p1
    return *obiekt + 1.0;
}
double funkcja2(double *obiekt)
{
    *obiekt += 1;
    return *obiekt + 2.0;
}
 

Mam tutaj dwie deklaracje funkcji, funkcja1 która jako argument przyjmuje wskaźnik do obiektów typu const double, oraz funkcja2 która przyjmuje wskaźnik do obiektów double. Z tym, że jeżeli funkcje1 wywołamy z argumentem typu double bez przydomku const, nie ma problemu - zwyczajnie kompilator potraktuje ją jak obiekt, który taki właśnie przydomek ma (w linii p1 jest nawet pokazane, ze taka operacja nie jest dozwolona, mimo iż obiekt, który do tej funkcji wysłaliśmy, jest typu double). Wywołanie natomiast funkcji funkcja2 w taki sposób, że wyślemy do niej adres do obiektu stałego, jako iż argumentem, który przyjmuje jest wskaźnik do obiektów typu double zakończy się błędem kompilacji (czego należało się spodziewać).

W symfonii jest napisane, iż przeładowanie nazwy funkcji działa na zasadzie rozróżniania typów argumentów. Czyli jeżeli mamy funkcję:

void fun(double);
void fun(char);
 

I wywołamy ją w taki sposób:

 fun(3.2);

To kompilator będzie wiedział, do której funkcji to się odnosi ( bo przecież tak przesłany argument aktualny pasuje tylko do jednej z tych funkcji.

I tutaj dochodzimy do mojego pytania: Dlaczego jeżeli mamy np. taki krótki programik:

#include <iostream>
using namespace std;
double funkcja(const double *obiekt);
double funkcja(double *obiekt);
int main() {
    double zmienna = 4.0;
    cout << funkcja(&zmienna) << endl;
    return 0;
}
double funkcja(const double *obiekt)
{
    //*obiekt += 1; // p1
    return *obiekt + 1.0;
}
double funkcja(double *obiekt)
{
    *obiekt += 1;
    return *obiekt + 2.0;
}
 

To kompilator wie, że musi wywołać funkcje, która odbiera argument jako wskaźnik do double, kiedy takie wywołanie:

funkcja(&zmienna); 

pasuje do obu funkcji? Oraz w jaki sposób w takiej sytuacji wymusić, aby funkcją, która zostanie wywołana, była ta, która przyjmuje jako argument wskaźnik do const double?

Wybaczcie mi taki troszkę przydługi wstęp, ale nie wiem jak w krótszy sposób mógłbym opisać ten problem z interpretacją tego, co pisze w książce.

Z góry dziękuję za odpowiedź.
Pozdrawiam

Pozostało 580 znaków

2011-08-24 20:00
qwe
1

jeśli masz funkcje np:

double fun(const double *pi);
//oraz:
doube fun(double *pi);
 
a w main zmienne:
 
const double pi1 = 3.14;
double pi2 = 3.1
 
mozesz funkcje "fun" wywolać dwojako:
fun(&pi1); // pi1 jest typu "const doblue" wiec automatycznie zostanie wywolana funkcja double fun(const double *pi);
lub:
fun(&pi2); // pi2 jest typu "double" wiec automatycznie zostanie wywolana funkcja doube fun(double *pi);
 

Nie wiem czy o to Ci chodzilo, dość długi wstęp był ;<

Nie o to niestety :P W wielkim skrócie, chodziło mi o to, jak, mając zmienną typu double i dwie funkcje void fun(double wsk) oraz void fun(const double wsk) używajac argumentu double wywołać funkcję, która odbierze adres tego obiektu jako const double *wsk. - transient 2011-08-24 20:04
@transient: do tego używa się referencji a nie wskaźników. - vpiotr 2011-08-25 08:27

Pozostało 580 znaków

2011-08-24 20:10
funkcja(static_cast<const double*>(&zmienna));

Odradzam takie przeładowanie - jest mocno nieczytelne i okrutnie łatwo o pomyłkę - a potem szukaj igły w stogu siana

//edit: użycie wskaźnika do funkcji

double (*fun)(const double*) = funkcja;
cout << fun(&zmienna) << endl;

edytowany 3x, ostatnio: byku_guzio, 2011-08-24 20:58
Pokaż pozostałe 2 komentarze
Jest jeszcze jeden sposób(dodałem do postu) ;) - byku_guzio 2011-08-24 20:57
@byku_guzio: Nie widzę nic złego w takim rzutowaniu - nie chcę się pozbyć "const" tylko zmienić typ. Ale nie wiem do czego się ta wypowiedź odnosi bo powyżej nic o tym nie ma. qwe właściwie na wszystko odpowiedział. - vpiotr 2011-08-25 08:23
w rzutowaniu nie ma nic złego, ale takie przeładowanie funkcji jest nieczytelne(dla double robi jedno, dla const double zupełnie co innego), łatwo o błąd i źle się taki kod czyta. A moja wypowiedź odnosi się do tego pytania autora: "Oraz w jaki sposób w takiej sytuacji wymusić, aby funkcją, która zostanie wywołana, była ta, która przyjmuje jako argument wskaźnik do const double?" - byku_guzio 2011-08-25 12:36
Zgadzam się, efekt końcowy powinien być ten sam w obu funkcjach. - vpiotr 2011-08-26 13:11
Tak nie do końca, przykładowo powiedzmy operator powinien zwracać T&, a operator const powinien zwracać const T&. Podobnie jest ze zwracaniem iteratorów/const_iteratorów. - Zjarek 2011-08-26 13:44

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0