2013-03-26 16 views
7

Jestem nowy w c++ i mam problemy z konstruktorem i klasami. Tak, tu jest mój plik nagłówka:Brak odpowiedniego konstruktora do konwertowania z "testu *" na "test", konstruktora,

#pragma once 
#include <string> 
using namespace std; 
class test 
{ 

    private: 
    string name; 
    int number; 

public: 

    test(); 
    test(string i,int b); 
}; 

To cpp plik:

#include "test.h" 
#include <string> 
using namespace std; 


test::test(){} 

test::test(string i,int b){ 
    this->name=i; 
    this->number=b; 
} 

teraz, gdy próbuję zadzwonić

test t=new test("rrr",8); 

uzyskać:

1 IntelliSense: no suitable constructor exists to convert from "test *" to "test" 

Tak, co jest z klasami mającymi * w ich nazwie (na przykład, klasy bez pliku .cpp nie mają asterixa, wszystkie inne robią)? I co mam zrobić źle?

Odpowiedz

21

Wyobrażam sobie, że pochodzisz z tła Java/C#. t nie jest tutaj typem odniesienia, jest to typ wartości. new zwraca wskaźnik do obiektu. Więc trzeba jedną z następujących czynności:

test t = test("rrr", 8); 
test t("rrr", 8); 
test *t = new test("rrr", 8); 

Jeśli jeszcze nie jesteś zaznajomiony ze wskaźnikami, to na pewno nie używać ostatni! Ale zrozumienie semantyki wskaźników jest dość krytyczne; Polecam czytanie odpowiedniego rozdziału (y) w swoim podręczniku ...

+0

Miło, twoja odpowiedź jest znacznie lepsza niż moja :) +1 –

+0

tnx dużo. zgadłeś, zrobiłem programowanie w java i C# tak im trochę walczę z C++ :) .... – klo

+0

@klo Jeśli spróbujesz zaprogramować C++ tak, jak zaprogramowałeś Javę, zrobisz mnóstwo błędów. Nie są wcale bardzo podobne. – john

2
test t=new test("rrr",8); 

musi być

// v 
test* t=new test("rrr",8); 

Więc, co jest rzeczą z klas posiadających "*" w nazwie

* służy do wskazania wskaźnika, to nie w imieniu klasy. Ale to duży temat, więc powinieneś zrobić kilka badań na ten temat.

0

Nie określić t jako wskaźnik:

test* t=new test("rrr",8); 

Albo po prostu

test t = test("rrr",8); 
0
T* t = new T; 
//  ^^^ 

Kiedy jest nowy użyte w tej konstrukcji obiektu, oznacza utworzenie wskaźnika. To, co robisz, to dynamiczne przydzielanie pamięci, której jestem pewna, że ​​nie chciałeś zrobić. Raczej typowa konstrukcja stosu przydzielone obiektu odbywa się po prostu tak:

T t; 

Nawet jeśli miał zamiar się na tworzeniu i wskaźnik alokacji pamięci, zrobiłeś to w niewłaściwy sposób. Wskaźnik jest tworzony z symbolem *, którego nie ma w kodzie. Po drugie, kiedy skończysz używać pamięci, którą utworzyłeś, musisz pamiętać o swoim kodzie delete/delete[]. delete[] jest używany w dynamicznie przydzielanych tablicach.Tak to jest, jak to będzie wyglądać za wskaźnikiem:

delete t; 
1

* nie jest częścią nazwy, jest to modyfikator oznaczający, że obiekt jest wskaźnik. Wskaźnik jest zmiennym adresem trzymania w pewnym miejscu w pamięci, w którym przechowywany jest rzeczywisty obiekt. Pewne podstawy:

int i = 5; 
int * pI = &i; 

int * pI środki, które chcesz zadeklarować wskaźnik na miejsce w pamięci, gdzie int jest utrzymywany. &i oznacza, że ​​chcesz pobrać wskaźnik do zmiennej. Teraz pI przechowuje adres w pamięci, gdzie jest przechowywany. Teraz można dereference wskaźnik - dostać się do wartości wskaźnika:

int j = *pI; 

teraz poinformować kompilator, że powinien iść do adresu wskazywanego przez PI i retreive jego zawartość (od pI jest wskaźnikiem do int, kompilator przyjmie, że jest tam int).

Teraz wracamy do twojego przykładu. new operator przydziela pamięć dynamicznie dla obiektu, więc:

new test("rrr", 8); 

wyniki przydzielania pamięci dla klasy testowej, wywołanie konstruktora z parametrami „RRR” i 8 oraz powrocie wskaźnik do przydzielonej pamięci. Dlatego nie można go przypisać do zmiennej test: new operator w tym przypadku zwraca wartość test *.

Spróbuj kod:

test * t = new test("rrr", 8); 
5

Więc, co jest rzeczą z klas posiadających „*” w nazwie (na przykład zajęcia bez pliku .cpp nie masz Asterix, wszyscy inni) ?? ?

Zdecydowanie trzeba poznać wskaźniki. test * i test to dwa zupełnie różne typy w C++. Oto dwie zmienne z tymi typami:

test t; 
test* p; 

tutaj, t ma typ test i p jako typ test*. Opisujemy test* jako "wskaźnik do test".

Często można myśleć o wskaźniku jako o adresie pamięci obiektu. Tak więc w p, ponieważ jest to wskaźnik, możemy zapisać adres pamięci t, który jest test. Aby uzyskać adres obiektu, używamy jednoargumentowy & operatora, tak jak poniżej:

test t; 
test* p = &t; 

Zauważ, że tjesttest przedmiot. Nie trzeba było mówić new test(). To jest, gdzie C++ różni się od innych języków, które mogłeś używać, takich jak C# i Java. W powyższym kodzie C++ t jest obiektem test.

Możesz jednak może utworzyć obiekty z new test(), więc jaka jest różnica?

test t; tworzy obiekt test z automatycznym czasem przechowywania. Oznacza to, że jest niszczony na końcu swojego zakresu (często funkcja jest deklarowana w ramach).

new test() tworzy obiekt test z dynamicznym czasem przechowywania. Oznacza to, że musisz ręcznie zniszczyć obiekt, w przeciwnym razie wystąpi przeciek pamięci. To wyrażenie zwraca wskaźnik i tak można zainicjować obiektu wskaźnika z nim:

test* p = new test(); 

Więc teraz przyjrzyjmy się swojego problemu:

test t=new test("rrr",8); 

Teraz wiemy, że new test("rrr", 8) zwraca wskaźnik do test (a test*). Jednak próbujesz przypisać go do obiektu test. Po prostu nie możesz tego zrobić. Jednym z nich jest adres, a drugi to test. W związku z tym kompilator mówi "nie ma odpowiedniego konstruktora do przekonwertowania z test * do test." To ma sens, prawda?

Zamiast tego należy używać automatycznego czasu przechowywania. Używaj tylko new, jeśli naprawdę potrzebujesz. Tak po prostu:

test t("rrr", 8);