Błąd linkEr i metoda wirtualna

0

Witam.

Tworzę sobie taką jedną grę no i wszystko zrobiłem, ale coś mi się nie kompiluje,

class gracz
{
public:
	virtual void graj(char plansza[][M]) = 0;
};

A to jest klasa pochodna:

class uzytkownik:public gracz
{
public:

	 void graj(char plansza[][M]);
};

Powyższe to fragmenty nagłówków.

No i jak próbuję to kompilować, to wyskakuje mi błąd:
<cod>Error 1 error LNK2001: unresolved external symbol "public: virtual void __thiscall uzytkownik::graj(char (* const)[8])" (?graj@uzytkownik@@UAEXQAY07D@Z) C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Projekt PO\Main.obj Projekt PO

oraz

Error 2 error LNK1120: 1 unresolved externals C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Debug\Projekt PO.exe 1 1 Projekt PO


O co w tym chodzi?

Zastosowałem dyrektywy ifndef, wszystko podzielone na pliki i ogólnie wszystko gra, tylko z tą metodą wirtualną jest jakiś problem.
Nie mogę wkleić całego programu, bo to 1500 lini.
Na stronie MSDN czytałem na ten temat, ale nie doszedłem do końca o co chodzi.
Ktoś ma jakiś pomysł?
0

No a ciało (definicja) tej metody gdzieś jest? Kompiluje się?

0

W klasie bazowej znajduje się deklaracja, a definicje są wszystkie w klasach bazowych. Wszystko się kompiluje i przy linkowaniu wyskakuje błąd.

0

Może spytam inaczej to co spytał wyżej @Endrju: - co robi ta metoda graj?
Linkier się buntuje bo tego nie wie.

0

Jednak nie poszło.
Istota tego jest taka, że metoda wirtualna graj jest zadeklarowana w klasie bazowej jako abstrakcyjna, a jej definicje są umieszczone w kilku klasach pochodnych. Używając wskaźnika na klasę bazową, chcę uruchomić po kolei każdą z tych metod umieszczoną w klasie pochodnej.
Zakładam, iż w takim wypadku jedynie deklaruję metodą w klasie bazowej jako wirtualną i nie podaję jej definicji, robię to dopiero w klasie pochodnej.
Czy ja coś źle kumam?

0

dobrze kumsz, ale najwyraźniej nie masz czegoś takiego, w pliku *.cpp:

void uzytkownik::graj(char plansza[][M]) {
    // jakiś kod tutaj
}

Względnie plik, w którym to mas nie jest częścią projektu (nie jest kompilowany i nie jest łączony do pliku wynikowego).

0

Dodałem ten wpis, ale ciagle cos mi nie działa. Klasa uzytkownik jest klasą pochodną, klasą bazową jest klasa gracz. Zrobiłem tak jak napisałeś powyżej, ale nie idzie ciągle.
A co z deklaracjami tych funkcji w pliku nagłówkowym?
Czy piszę wtedy tak samo jak powyżej, czy po prostu void graj(char plansza[][M]);

0

Gdy definiujesz jakąkolwiek nazwę wewnątrz struktury, klasy bądź przestrzeni nazw to kwalifikator nazwy nie jest wymagany (np. void Gracz::graj(); gdzie Gracz:: nie jest wymagany). Gdy jesteś już poza zasięgiem leksykalnym (kontekstowym) nazwy, którą chcesz zdefiniować, to kwalifikator nazwy musi być podany, dlatego że linker musi wiedzieć, do kogo należy ta metoda. Przecież metod o nazwie graj może być wiele.

0
aaquillus napisał(a):

Dodałem ten wpis, ale ciagle cos mi nie działa.
Opanuj może najpierw zwykłe metody, zanim się zabierzesz za dziedziczenie i metody wirtualne…

0

Dziekuję, zwykłe metody mam już opanowane.

0

Załapałem już o co chodzi, wszystko poszło, ale utkwiłem na kilku innych metodach.

#include <iostream>
#include <string>

#include "class_uzytkownik.h"
#include "class_gracz.h"
#include "def_fun.h"
#include "Structures.h"

using namespace std;
#define M 8

void uzytkownik::graj(char plansza[][M])
	{
		pole pionek, cel;
		string gracz1;
		cout<<"Podaj nazwe gracza nr 1:";
		cin>>gracz1;
		string gracz2;
		cout<<"Podaj nazwe gracza nr 2:";
		cin>>gracz2;

		cout<<" \n Zaczynamy gre. Wiersze i kolumny sa numerowane od 0 do 7. Gracz "<<gracz1<<" jest oznaczony jako kolko, a "<<gracz2<<" jako krzyzyk"<<endl;
		cout<<"Damka gracza "<<gracz1<<" jest oznaczona jako D, a damka gracza "<<gracz2<<" jest oznaczona jako K\n\n"<<endl;
		
		wynik wynik_gry={12,12};

		while(wynik_gry.gracz1>0&&wynik_gry.gracz2>0)
		{
		cout<<"Teraz gra "<<gracz1<<"\n"<<endl;
			pionek=uzytkownik::wczytaj_ktory_pionek(plansza,'O','D','X', 'K');
			cel=uzytkownik::wczytaj_gdzie_przesunac(plansza, pionek,'O','D', 'X','K');
			uzytkownik::przesun_pionek(plansza, pionek, cel, &wynik_gry);
			pokaz_plansze(plansza);
			cout<<"\nIlosc pionkow gracza "<<gracz1<<" wynosi "<<wynik_gry.gracz1<<endl;
		cout<<"Teraz gra "<<gracz2<<endl;
			pionek=uzytkownik::wczytaj_ktory_pionek(plansza,'X','K','O', 'D');
			cel=uzytkownik::wczytaj_gdzie_przesunac(plansza, pionek, 'X','K','O','D');
			uzytkownik::przesun_pionek(plansza,pionek,cel, &wynik_gry);
			pokaz_plansze(plansza);
			cout<<"Ilosc pionkow gracza "<<gracz2<<" wynosi "<<wynik_gry.gracz2<<endl;
		}	
		if(wynik_gry.gracz1==0)
		{
			cout<<"Gra zostala zakonczona. Wygral gracz "<<gracz2;
		}
		if(wynik_gry.gracz2==0)
		{
			cout<<"Gra zostala zakonczona. Wygral gracz "<<gracz1;
		}
	}


jest to klasa dziedzicząca z klasy gracz, zaś te 3 metody zostały zadeklarowe w pliku class_gracz.h oraz zdefiniowane w pliku class_gracz.cpp.
I znowu przy linkowaniu wywala mi błąd

Error	1	error LNK2019: unresolved external symbol "protected: void __thiscall gracz::przesun_pionek(char (* const)[8],struct pole,struct pole,struct wynik *)" (?przesun_pionek@gracz@@IAEXQAY07DUpole@@1PAUwynik@@@Z) referenced in function "public: virtual void __thiscall gracz::graj(char (* const)[8])" (?graj@gracz@@UAEXQAY07D@Z)	C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Projekt PO\class_uzytkownik.obj	Projekt PO
Error	2	error LNK2019: unresolved external symbol "protected: struct pole __thiscall gracz::wczytaj_gdzie_przesunac(char (* const)[8],struct pole,char,char,char,char)" (?wczytaj_gdzie_przesunac@gracz@@IAE?AUpole@@QAY07DU2@DDDD@Z) referenced in function "public: virtual void __thiscall gracz::graj(char (* const)[8])" (?graj@gracz@@UAEXQAY07D@Z)	C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Projekt PO\class_uzytkownik.obj	Projekt PO
Error	3	error LNK2019: unresolved external symbol "protected: struct pole __thiscall gracz::wczytaj_ktory_pionek(char (* const)[8],char,char,char,char)" (?wczytaj_ktory_pionek@gracz@@IAE?AUpole@@QAY07DDDDD@Z) referenced in function "public: virtual void __thiscall gracz::graj(char (* const)[8])" (?graj@gracz@@UAEXQAY07D@Z)	C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Projekt PO\class_uzytkownik.obj	Projekt PO
Error	4	error LNK2001: unresolved external symbol "public: virtual void __thiscall uzytkownik::graj(char (* const)[8])" (?graj@uzytkownik@@UAEXQAY07D@Z)	C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Projekt PO\Main.obj	Projekt PO
Error	5	error LNK1120: 4 unresolved externals	C:\Users\Kamil\Documents\Visual Studio 2010\Projects\Projekt PO\Debug\Projekt PO.exe	Projekt PO

Doszedłem do wniosku, że być może linkier nie może powiązać metody z jej definicją, ale nie wiem dlaczego.

0

Nie grzesz więcej, bo moje oczy krwawią.
Lepiej napisz to jeszcze raz :L

0

Czy ktoś ma pomysł co z tym zrobić?

0

IMO zrobiłeś błąd projektowy. W twoim programie nie trzeba tworzyć metod wirtualnych. Nie ma sensu po prostu. Radzę, żebyś przestudiował temat dokładniej. Może ci wyjaśnię...
Mamy 3 instrumenty - gitarę, saksofon i skrzypce. Na każdym się oczywiście gra inaczej. Do tego są funkcje wirtualne, aby uruchomić metodę zależną od podstawionego typu pod zmienną. Mamy wskaźnik do instrumentów, gdzie jest podstawiony jest adres skrzypiec. Gdy uruchomimy inst->graj(); to powinno nam odpalić metodę graj skrzypiec (oczywiście mówimy tu o metodach wirtualnych).

Ty tutaj napisałeś praktycznie cały kod programu pod jedną metodę. Musisz jeszcze trochę się poduczyć.

0

Nie do końca tak jest, bo w sumie mają być 3 klasy dziedziczące i każda ma mieć inaczej zdefiniowaną tą metodę. Sprawę poliformizmu jeszcze dokładnie przestudiuję, ale pytanie moje w tej sprawie pozostaje : czy w obecnej wersji da się to jakoś uruchomić?
Bo niestety siedzę nad tym już trochę czasu i ciągle mi wywala ten sam błąd linkera...

0

Jeżeli to nie błąd linkera, to co to jest?

0

Poradziłem sobie z tym problemem, dziękuję za pomoc.

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