Pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter, inscrivez-vous gratuitement !

 

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    mars 2010
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2010
    Messages : 47
    Points : 48
    Points
    48

    Par défaut Déclaration de tableau E0070 type incomplet non autorisé

    j'apprend à ce moment le C++ et essayer de convertir du code C# mais le compilateur me sort des erreurs dont je n'arrive pas à trouver de solution

    je précise de prime abord que je ne maitrise pas quels sont les éléments à mettre dans les fichier d’entête ou pas
    je dev une librairie de génération de bruit à n dimension avec des classes imbriquées et je passe en paramètre des tableaux à une fonction ( méthode) dont la dimension n'est pas connu à l'avance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    		class Perlin
    			{
     
     
    				//
    				private: double DotGridToGradient( long IdxCoord[] , long Coord[])
     
    					double RetGrad;
    					long DCoord[];
     
    					// inserer le calcul  gradient
    					//
    					for (long i=0; i< Coord.size(); i++)
    c'est dans le fichier .cpp avec les includes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include "monfichier.hpp"
    #include <array>
    #include <iostream>
    mon fichier .hpp est vide pour l'instant hormis les includes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <iostream>
    #include <stdarg.h>
    #include <stdlib.h>
    long DCoord[] : renvoi l'erreur E0070 type incomplet non autorisé
    Coord.size() : renvoi l'erreur E0153 l'expression doit avoir un type classe
    comment autorisé un type incomplet dans une classe en déplaçant a la fin de celle ci la déclaration ?

    je compile cela sous Ms Visual studio 2017 express avec les reglages suivants :

    /permissive- /GS /W4 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"x64\Debug\vc141.pdb" /Zc:inline /fp:precise /D "_MBCS" /errorReport:prompt /doc"x64\Debug\" /WX- /Zc:forScope /RTC1 /Gd /MDd /FC /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\NoiseGenerator-Win.pch" /diagnostics:classic

  2. #2
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 376
    Points : 23 175
    Points
    23 175

    Par défaut

    Salut,

    porter un code de C# à C++ ne se résume pas à un simple copier/coller.
    long DCoord[]; déclare un tableau de taille inconnu. Donc cette déclaration est impossible pour créer une variable. (la syntaxe existe et est possible, dans certains cas où tu ne te trouves pas).
    long Coord[] déclare toujours un tableau de taille inconnu. Et le type tableau n'existe pas en C++, donc la fonction membre size encore moins.
    Les tableaux en C++ sont std::vector (dynamique) ou std::array (si la taille est connue à la compilation).
    stdarg.h est un include C, l'équivalent C++ est cstdarg.
    stdlib.h est un include C, l'équivalent C++ est cstdlib.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    mars 2010
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2010
    Messages : 47
    Points : 48
    Points
    48

    Par défaut

    ce n'est pas du copîé coller tout du moins je me suis basé sur des tutorial et la consultation de la doc suivante https://msdn.microsoft.com/fr-fr/library/200xfxh6.aspx
    et le cours du site https://cpp.developpez.com/cours/cpp/?page=page_3
    Nom : Array.jpg
Affichages : 58
Taille : 85,9 Ko

    tu dis que long Coord[] déclare toujours un tableau de taille inconnu. c'est normal vu que c'est une déclaration ( initialisation) du passage par valeur long *Coord[] me retourne le même problème

    j'ai un struct où la syntaxe est la même qui ne me renvois pas d'erreur car suivant la doc ( ms ) il faut placer en fin de déclaration la variable tableau en fin
    alors que pour une classe ou une methode rien n'est specifié dans les doc et tuto que j'ai consulté
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef struct NoiseData NoiseData;
    		struct NoiseData
    		{
    			public: 
    				[readonly] long NDim;
    				[readonly] bool TpInterPol;
    				[readonly] long Coord[];
    Edit : avec new j'ai trouver la syntaxe qui ne me sort pas d'erreur long* DCoord = new long[];
    mais si j'essai d'initialiser la taille du tableau DCoord avec la fonction size sur le tableau Coord passé en paramètre l'erreur persiste

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2004
    Messages
    5 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2004
    Messages : 5 431
    Points : 15 746
    Points
    15 746

    Par défaut

    Il existe deux façons (principales) de faire des tableaux en C++ : La version de base directement dans le langage, bas niveau, risquée, peu flexible, et la version dans la bibliothèque, plus sécurisée, plus simple, avec plus de fonctionnalités, et tout aussi rapide. La doc que tu cites parle de la première, mais je te conseille vivement de l'oublier, et d'écouter ce bon conseil de Bousk : En première approximation (et aussi en deuxième, et probablement en troisième), un tableau en C++, c'est std::vector ou std::array, selon que la taille est ou pas connue à la compilation.

    Oublie aussi ton [readonly] : Ce n'est pas du C++ standard, et ça ne sert pas à grand'chose. L'équivalent C++ serait const, même si je ne suis pas certain de la pertinence ici. Oublie aussi la syntaxe typedef struct, utilise juste struct.

    Et sinon, peut-être que de suivre un tuto sur le C++ serait un investissement vite rentabilisé...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    Consultant informatique
    Inscrit en
    octobre 2004
    Messages
    10 866
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : octobre 2004
    Messages : 10 866
    Points : 25 248
    Points
    25 248

    Par défaut

    Salut,

    On va essayer d'expliquer les choses un peu plus en profondeur...

    Oui, les symboles [ et ] permettent (grâce à l'héritage issu du C) de définir des tableaux de données, mais à la condition expresse d'indiquer explicitement le nombre d'éléments que le tableau devra contenir.

    Le compilateur a -- en effet -- besoin de connaitre le type des éléments que le tableau doit contenir ainsi que leur nombre pour pouvoir déterminer l'espace total qu'il doit prévoir en mémoire afin de permettre la représentation de tous ces éléments.

    Ainsi, quand tu utilises le code int tab[10]; le compilateur sait qu'il doit prévoir en mémoire un espace suffisant pour représenter 10 entiers consécutifs en mémoire, et comme il connait la taille du type int (qui nécessite classiquement 4 bytes pour pour pouvoir reprsenter l'ensemble des valeurs qu'il accepte), il pourra calculer "sans difficulté" l'adresse mémoire à laquelle devra aller la première information qui suit le tableau qu'on lui a demandé de représenter.

    Ainsi, si le compilateur détermine que le premier élément du tableau doit se trouver à l'adresse adr dont la valeur est -- mettons 0x002 il saura qu'il devra garder 10 * 4 = 40 bytes pour pouvoir représenter les dix entiers et qu'il ne pourra rien représente d'autre que des entiers en mémoire avant l'adresse adr + 40 = 0x002 + 0x28 = 0x02A.

    Maintenant, lorsque le compilateur rencontre un code comme ton long IdxCoord[] ou ton long Coord[];, lui, ce qu'il comprend c'est que tu lui dit en gros :
    Je veux pouvoir représenter "un certain nombre" de valeurs de type long successifs en mémoire
    Alors, bien sur, il connait la taille que va prendre un long en mémoire (typiquement 4 ou 8 bytes) mais, comme tu as parlé "d'un certain nombre" sans préciser combien, le compilateur n'a absolument aucun moyen de déterminer ... l'espace qu'il devra prévoir entre le premier élément de cet ensemble de donnée et ... la première donnée qui viendra après.

    Voilà pourquoi le compilateur n'accepte pas la manière dont tu lui indique tes tableaux

    Alors, il y a plusieurs solutions : les plus simples et sécurisantes à l'usage sont celles que bousk t'a conseillées: utiliser les classes std::vector si le nombre d'éléments n'est pas connu à la compilation et std::array si tu connais le nombre d'éléments que ton tableau devra contenir au moment de compiler ton code.

    Une alternative possible que je ne cite que "pour mémoire", dans le but d'être complet et que je te déconseille largement d'utiliser est de travailler "à la mode C":

    En effet, un tableau d'éléments dont le type est connu est identifié -- au niveau du compilateur -- par l'adresse mémoire à laquelle se trouve le premier élément du tableau en question; chaque élément allant s'installer à une adresse mémoire décalée du nombre de bytes nécessaire pour représenter un élément par rapport à l'adresse mémoire à laquelle se trouve... l'élément qui le précède dans le tableau.

    Pour qu'une fonction qui doit manipuler "un certain nombre" de double puisse travailler correctement, nous pouvons donc lui transmettre une adresse mémoire qui représente le premier élément du tableau et une valeur correspondant au nombre d'éléments qu'elle devra manipuler sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void foo(long * ptr,    // l'adresse du premier élément du tableau
             size_t size ){ // le nombre d'éléments du tablea
        /* ... */
    }
    Seulement, si le nombre d'éléments que doit contenir le tableau n'est connu qu'à l'exécution, nous ne pouvons forcément pas compter sur le compilateur pour qu'il se charge de réserver l'espace mémoire qui sera nécessaire pour représenter ce nombre (inconnu au moment où il fait son taf) d'éléments .

    Nous devrons donc demander au système d'exploitation "d'avoir la gentillesse" de nous fournir un espace mémoire suffisant, et de le réserver à l'usage de notre application, par exemple sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int main(){
        size_t laTaille;
        /* on détermine la taille du tableau */
        long * leTableau= new long[laTaille];
        /* maintenant que l'on a les deux, on peut faire
         * appel à  foo en les lui transmettant 
         */
        foo(leTableau, laTaille);
        /* quand on n'a plus besoin du tableau, on peut rendre
         * l'espace mémoire correspondant au système d'exploitation
         */
        delete [] leTableau;
        /* ... */
    }
    Seulement, cette manière de travailler va poser énormément de problèmes. Comme mon intervention atteint tout doucement la taille d'un roman, je ne vais pas en parler ici, mais je reste à ta disposition pour te les expliquer en cas de besoin

    C'est la raison pour laquelle je disais avant l'explication que je ne citais cette solution que pour mémoire, mais que j'en déconseillais l'usage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Déclaration de tableau du type Class..
    Par jeffciara dans le forum Général Java
    Réponses: 8
    Dernier message: 16/05/2011, 14h22
  2. Réponses: 1
    Dernier message: 18/01/2010, 17h23
  3. erreur 3251 opération non autorisé pour ce type d'objet
    Par alexkickstand dans le forum VBA Access
    Réponses: 3
    Dernier message: 28/02/2008, 21h39
  4. Problème element du tableau de type incomplet
    Par OlivierDotre dans le forum Débuter
    Réponses: 2
    Dernier message: 04/11/2007, 15h26
  5. Erreur 3251: Opération non autorisé pr ce type d'objet
    Par Ragnarok85 dans le forum Access
    Réponses: 10
    Dernier message: 14/02/2007, 09h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo