c++ “Onvolledig type niet toegestaan”-fout bij toegang tot klassereferentie-informatie (Circulaire afhankelijkheid met voorwaartse declaratie)

Er waren onlangs wat problemen in mijn code rond wat ik nu ken als een circulaire afhankelijkheid. Kort gezegd zijn er twee klassen, Player en Ball, die beide informatie van de andere moeten gebruiken. Beiden krijgen op een bepaald punt in de code een referentie van de andere (van een andere klasse die beide .h-bestanden zal bevatten).

Na erover gelezen te hebben, heb ik de #include.h-bestanden van elk verwijderd en ben ik verder gegaan met declaratie. Dit loste het probleem op om de klassen in elkaar te kunnen declareren, maar ik heb nu een “Onvolledige typefout” wanneer ik probeer toegang te krijgen tot een doorgegeven verwijzing naar het object. Er lijken een paar vergelijkbare voorbeelden te zijn, hoewel vaak vermengd met complexere code en moeilijk te beperken tot de basis.

Ik heb de code herschreven in zijn eenvoudigste vorm (in wezen een skelet).

Bal.h:

class Player;
class Ball {
public:
    Player& PlayerB;
    float ballPosX = 800;
private:
};

Speler.h:

class Ball;
class Player {
public:
    void doSomething(Ball& ball);
private:
};

Speler.cpp:

#include "Player.h"
void Player::doSomething(Ball& ball) {
    ball.ballPosX += 10;                   // incomplete type error occurs here.
}

Alle hulp om te begrijpen waarom dit het geval is, wordt zeer op prijs gesteld 🙂


Antwoord 1, autoriteit 100%

Als u uw definities in deze volgorde plaatst, wordt de code gecompileerd

class Ball;
class Player {
public:
    void doSomething(Ball& ball);
private:
};
class Ball {
public:
    Player& PlayerB;
    float ballPosX = 800;
private:
};
void Player::doSomething(Ball& ball) {
    ball.ballPosX += 10;                   // incomplete type error occurs here.
}
int main()
{
}

De definitie van de functie doSomething vereist de volledige definitie van klasse Ball omdat deze toegang heeft tot zijn gegevenslid.

In uw codevoorbeeldmodule heeft Player.cpp geen toegang tot de definitie van klasse Ball, dus de compiler geeft een foutmelding.


Antwoord 2, autoriteit 79%

Player.cppvereist de definitie van de klasse Ball. Dus voeg gewoon #include "Ball.h"

toe

Speler.cpp:

#include "Player.h"
#include "Ball.h"
void Player::doSomething(Ball& ball) {
    ball.ballPosX += 10;                   // incomplete type error occurs here.
}

Antwoord 3, autoriteit 7%

Dit is wat ik had en wat mijn “onvolledige typefout” veroorzaakte:

#include "X.h" // another already declared class
class Big {...} // full declaration of class A
class Small : Big {
    Small() {}
    Small(X); // line 6
}
//.... all other stuff

Wat ik deed in het bestand “Big.cpp”, waar ik de constructor van A2 met X als parameter heb gedeclareerd, is..

Big.cpp

Small::Big(X my_x) { // line 9 <--- LOOK at this !
}

Ik schreef “Small::Big” in plaats van “Small::Small”, wat een domme fout..
Ik kreeg de hele tijd de foutmelding “onvolledig type is nu toegestaan” voor de klasse X (in regel 6 en 9), wat een totale verwarring veroorzaakte..

Hoe dan ook, dat is waar een fout kan gebeuren, en de belangrijkste reden is dat ik moe was toen ik het schreef en ik 2 uur nodig had om de code te verkennen en te herschrijven om het te onthullen.


Antwoord 4

In mijn geval was het vanwege een typefout.

Ik had zoiets als

struct SomethingStrcut { /* stuff */ };
typedef struct SomethingStruct smth;

Merk op dat de naam van de structuur niet dezelfde is als de typedefinitie.

Ik heb structverkeerd gespeld in strcut.

Bekijk je code en kijk of je typfouten hebt gemaakt.

Other episodes