Wskaźniki do string jako argument do funkcji

0

Mam pewien problem ze wskaźnikami, które próbuje użyć jako argumenty funkcji.

Pokaże tylko na przykładzie, powiedzmy że mamy jakąś strukturę, następnie tworzymy funkcję która będzie korzystała z danych w tej strukturze i umieszczała obiekty z nich złożone do np. kolejki priorytetowe.

 
struct Osoba
{
   string imie; 
   string nazwisko; 
   int wiek; 
}; 

priority_queue<Osoba, vector<Osoba>, KolejnoscSortowania> KolejkaOsob; // nie ma sensu chyba pokazywac co siedzi w KolejnoscSortowania...


void WstawNowaOsobe(KolejkaOsob &kp, const string *imie, const string *nazwisko, int wiek) 
{
    Osoba nowaOsoba; 
    nowaOsoba.imie = imie; 
    nowaOsoba.nazwisko = nazwisko; 
    nowaOsoba.wiek = wiek; 
} 

Pytanie:

Dlaczego stosując WSKAŹNIK NA TYP STRING, typu string dostaję błąd kompilatora:

invalid conversion from 'const string* {aka const std::basic_string<char>*{' to 'char' [-fpermissive];

Używając referencji zamiast wskaźnika nie dostaje tego błędu i wszystko się kompiluje:

 
void WstawOsobe(KolejkaOsob &kp, const string &imie, const string &nazwisko, int wiek); 

to się kompiluje.

Tak samo jak to:

 
void WstawOsobe(KolejkaOsob &kp, const char *imie, const char *nazwisko, int wiek); 

Tutaj też używam wskaźnika tylko że na tablicę znaków i działa, dlaczego nie działa gdy tworzę wskaźnik na string ?
Przecież typy się zgadzają, imie i nazwisko są typu string -> tworzę wskaźnik typu string do zmiennych typu string i nie działa...

Jakieś dokładne wytłumaczenie błędu logicznego albo wyjaśnienie w czym tkwi błąd było by na prawdę pomocne.

2

Przecież typy się zgadzają, imie i nazwisko są typu string -> tworzę wskaźnik typu string do zmiennych typu string i nie działa...

No i właśnie dlatego typy się nie zgadzają, imię i nazwisko są typu string, natomiast wskaźnik jest typu string*, czyli de facto (w przypadku architektury 32-bitowej) 4-bajtową zmienną, określającą pewien adres w pamięci.
Sprawa inaczej ma się przy przekazywaniu parametru przez referencję, na tym właśnie polega cała "magia" referencji, że stanową swego rodzaju stały wskaźnik na zmienną, a można je używać jak zwykłe zmienne.

1

Wskaźnik na typ, czyli T* i sam typ T to zupełnie różne rzeczy. Jak chcesz przypisać string pod wskaźnikiem do stringa, musisz dokonać dereferencji:

nowaOsoba.imie = *imie; 
0

Jeśli chcesz mieć opcjonalne parametry to najlepiej zrób tak:

void WstawNowaOsobe(KolejkaOsob &kp, const Osoba &osoba) 
{
...
} 

Inaczej będziesz musiał pisać tak (jeśli chcesz opcjonalne parametry):

WstawNowaOsobe(kp, NULL, NULL, 12);

Jeśli nie chcesz opcjonalnych parametrów to wystarczy zmienić nagłówek:

void WstawNowaOsobe(KolejkaOsob &kp, const string &imie, const string &nazwisko, int wiek) 
{
    Osoba nowaOsoba; 
    nowaOsoba.imie = imie; 
    nowaOsoba.nazwisko = nazwisko; 
    nowaOsoba.wiek = wiek; 
...
}
0

Dzięki za odpowiedź, ale spróbowałem zastosować się do Twojej rady i coś nie wychodzi.

 
struct Osoba
{
   string imie; 
   string nazwisko; 
   int wiek; 
}; 
 
priority_queue<Osoba, vector<Osoba>, KolejnoscSortowania> KolejkaOsob; // nie ma sensu chyba pokazywac co siedzi w KolejnoscSortowania...
 
 
void WstawNowaOsobe(KolejkaOsob &kp, const string *imie, const string *nazwisko, int wiek) 
{
    Osoba nowaOsoba; 
    nowaOsoba.imie = *imie; // ** Wspomniana przez Ciebie dereferencja 
    nowaOsoba.nazwisko = *nazwisko;  // ** -||-
    nowaOsoba.wiek = wiek; 
} 

Czy mam użyć tej dereferencji w argumencie funkcji ?

0

Może pokaże cały kod, a w komentarzu do Twojego postu się nie zmieści.

Błąd nie pokazuje w tym samym voidzie tylko gdy zaczynam go używać, mianowicie w mainie przy skorzystaniu z voida.
Cały kod:

#include <iostream> 
#include <string> 
#include <queue> 

using namespace std; 


struct Osoba
{
   string imie; 
   string nazwisko; 
   int wiek; 
   string RandomShit;
}; 

struct PorownajOsoby
{
   bool operator()(const Osoba &osoba1, const Osoba &osoba2) 
   { 
      if(osoba1.imie > osoba2.imie) return true; 
      if(osoba1.imie < osoba2.imie) return false; 

      return false; 
    } 
} ; 

typedef priority_queue<Osoba, vector<Osoba>, PorownajOsoby> KolejkaOsob; 

void WstawNowaOsobe(KolejkaOsob &kp, const string *imie, const string *nazwisko, int wiek, const string *RandomShit) 
{
    Osoba nowaOsoba; 
    nowaOsoba.imie = *imie;
    nowaOsoba.nazwisko = *nazwisko; 
    nowaOsoba.wiek = wiek; 
    nowaOsoba.RandomShit = *RandomShit; 
} 

int main(void)
{
   KolejkaOsob kolejkaMoja; 

   WstawNowaOsobe(kolejkaMoja, "Oleander", "Aleksandr", 12, "Costam"); // **Błąd: cannot convert 'const char*' to 'const string* {aka const std::basic_string<char>*}; for argument '2' to 'void WstawNowaOsobe(KolejkaOsob&, const string *, int, const string*); 
**
   WstawNowaOsobe(kolejkaMoja, "Oleanderx", "Aleksandrx", 13, "Costamz"); 
   WstawNowaOsobe(kolejkaMoja, "Oleanderxx", "Aleksandrxx", 14, "Costamsz");

 // Reszta funkcji be znaczenia bo błędy wyświetla tylko w trzech powyższych liniach

}  

 
2

Zrób sobie przysługę i używaj referencji.
Teraz pokaż wszystkie niejawne konwersje, jakie mogą zajść w kodzie

WstawNowaOsobe(kolejkaMoja, string("Oleander"), string("Aleksandr"), 12, string("Costam"));

Co się dzieje? Funkcja chce adres obiektu typu string, zaś ty przekazujesz jej obiekt typu string.
Kompilator w tym wypadku jasno krzyczy co jest nie tak.

1

"Aleksandrx" to tablica charów, nie string. Jeśli funkcja oczekuje wskaźnik na string to musisz jej go podać:

string oldeander = "Oleander";
string aleksandr = "Aleksander";
string costam = "Costam";
WstawNowaOsobe(kolejkaMoja, &oleander, &aleksandr, 12, &costam);

Ale w Twoim przypadku łatwiej będzie przyjmować char const* lub referencje.

0

No ale czego oczekiwałeś.

Podajesz c-string jako argument funkcji. Takie coś ma typ const char *. Funkcja oczekuje const std::string *. Tego nie da się skonwertować. Pytanie: dlaczego funkcja oczekuje takiego typu?

0

Robienie wskaźników na typy z STLa jak string czy vector to bardzo zły pomysł.
Użyj referencji.

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