1

I've been working on a C++ project for school and I'm currently facing this error :

LNK2005 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Vecteur2D const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVVecteur2D@@@Z)
already defined in Fonctions.obj    
Projet  E:\...\Solution_Projet\Projet\Point.obj

LNK2005 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Vecteur2D const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVVecteur2D@@@Z)
already defined in Fonctions.obj    
Projet  E:\...\Solution_Projet\Projet\Projet.obj

I searched for a solution on the web but didn't found anything relevant.

Here are the parts of my code which I think may cause this error. Most of the comments, names of var and names of functions are in French.

Projet.cpp

#include "pch.h"
#include "Point.h"
#include "Segment.h"
#include "Cercle.h"
#include "Triangle.h"
#include "Polygone.h"
#include "FormeGeoComplexe.h"

using namespace std;

void testPoint() {
    try {
        cout << "essais points 2D \n\n";
        Point u1("(2.54,3.85)");
        Point u2("(.54,-3.85)");
        Point u3("(.54,-.85)");
        Point v1("(8.12,1.055)");
        Point v2("(0.004,145.5023)");
        cout << "u1 donne" << u1 << endl;
        cout << "u2 donne" << u2 << endl;
        cout << "u3 donne" << u3 << endl;
        cout << "v1 donne" << v1 << endl;
        cout << "v2 donne" << v2 << endl;
        v1 = v1 * 2;
        cout << "v1*2 donne" << v1 << endl;
        v2 = -v2;
        cout << "-v2 donne" << v2 << endl;
        Point u4("2.54,3.85)");
        cout << "u4 donne" << u4 << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }
}

void testFormeGeo() {
    cout << "Liste des couleurs disponibles : " << Segment::getCouleursListe() << "\n" << endl;
}

void testSegment() {
    cout << "essais segments \n\n";

    try{
        Point u1("(2.54,3.85)");
        Point u2("(.54,-3.85)");
        Segment s1(u1, u2, "blue");
        cout << "s1 donne " << s1 << "\n" << endl;
        s1 = s1 * 8;
        cout << "s1 * 8 donne " << s1 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Segment s2("(2.54,3.85)", "(2.54,-3.85)", "red");
        cout << "s2 donne " << s2 << "\n" << endl;
        s2 = -s2;
        cout << "-s2 donne " << s2 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Segment s3(2.2, 3.5, 4.7, 6.7);
        cout << "s3 donne " << s3 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Segment s4;
        cout << "s4 donne " << s4 << " std::string " << (string)s4 << endl;
    }
    catch(Exceptions & e){
        cout << e.getMsg() << endl;
    }
}

void testCercle() {
    try {
        Point u1(2.1, 4.5);
        Cercle c1(u1, 4, "green");
        cout << "c1 donne " << c1 << "\n" << endl;
        c1 = c1 * 8;
        cout << "c1 * 8 donne " << c1 << "\n" << endl;
    }
    catch(Exceptions & e){
        cout << e.getMsg() << endl;
    }

    try {
        Cercle c2(2.4,6.3, 4, "yellow");
        cout << "c2 donne " << c2 << "\n" << endl;
        c2 = -c2;
        cout << "-c2 donne " << c2 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Cercle c3("(2.54,3.85)", 4, "yellow");
        cout << "c3 donne " << c3 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }
}

void testTriangle() {
    try {
        Point u1(2.1, 4.5);
        Point u2(5.1, 2.4);
        Point u3(-8.2, 0.5);
        Triangle t1(u1,u2,u3, "green");
        cout << "t1 donne " << t1 << "\n" << endl;
        t1 = t1 * 8;
        cout << "t1 * 8 donne " << t1 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Triangle t2(2.4, 6.3, 7.2, 9.3, 5.6, 9.2, "yellow");
        cout << "t2 donne " << t2 << "\n" << endl;
        t2 = -t2;
        cout << "-t2 donne " << t2 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Triangle t3("(2.54,3.85)", "(3.58,3.95)", "(1.64,1.85)", "yellow");
        cout << "t3 donne " << t3 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }
}

void testPolygone() {
    Point u1(2.3,4.5);
    Point u2(1.5,9.6);
    Point u3(9.4,7.1);
    Point u4(6.4,4.7);
    Segment s1(u1, u2, "blue");
    Segment s2(u3, u4, "yellow");
    Segment s3(u1, u3, "green");
    Segment s4(u2, u4, "red");

    vector<Segment>l1{s1,s2,s3,s4};
    try{
        Polygone p1(l1, "cyan");
        cout << "p1 donne " << p1 << "\n" << endl;
        cout << "p1 * 8 donne " << p1 * 8 << "\n" << endl;
        cout << "-p1 donne " << -p1 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    vector<Segment>l2{ s1,s2 };
    try {
        Polygone p2(l2, "cyan");
        cout << "p2 donne " << p2 << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

}

void testFormeGeoComplexe() {
    //triangle
    Point u1(2.1, 4.5);
    Point u2(5.1, 2.4);
    Point u3(-8.2, 0.5);
    Triangle t1(u1, u2, u3, "green");
    //segment
    Point u4(3.7, 4.1);
    Point u5(1.1, 7.2);
    Segment s1(u4, u5, "yellow");
    //cercle
    Point u6(9.5, 12.2);
    Cercle c1(u6, 4, "blue");
    //polygone
    Point u7(2.3, 5.3);
    Point u8(1.5, 9.6);
    Point u9(9.4, 7.1);
    Point u10(6.4, 4.7);
    Segment s2(u7, u8, "blue");
    Segment s3(u9, u10, "yellow");
    Segment s4(u7, u9, "green");
    Segment s5(u8, u10, "red");
    vector<Segment>l1{ s2,s3,s4,s5 };
    try {
        Polygone p1(l1, "cyan");
        FormeGeoComplexe fgc1(&p1,"blue");
        cout << "Polygone " << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        FormeGeoComplexe fgc2(&c1,"red");
        cout << "Polygone Cercle" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        FormeGeoComplexe fgc3(&t1,"yellow");
        cout << "Polygone Cercle Triangle" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        FormeGeoComplexe fgc4(&s1,"green");
        cout << "Polygone Cercle Triangle Segment" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        fgc1 + fgc2;
        cout << "3 ensembles" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        fgc1.Union(fgc3);
        cout << "2 ensembles" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        FormeGeoComplexe::Union(fgc1, fgc4);
        cout << "1 ensemble" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

        FormeGeoComplexe::supprimerEnsemble(fgc1);
        cout << "vide" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;

    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }

    try {
        Polygone p1(l1, "cyan");
        FormeGeoComplexe fgc1(&p1);
        cout << "Polygone " << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;
        FormeGeoComplexe fgc10(&p1);
        FormeGeoComplexe::supprimerEnsemble(fgc1);
        cout << "vide" << endl;
        cout << FormeGeoComplexe::toStringObj() << "\n" << endl;
    }
    catch (Exceptions & e) {
        cout << e.getMsg() << endl;
    }
}

int main()
{
    cout << "Hello World!\n\n";
    //essais Point
    testPoint();
    //essai FormeGeo
    testFormeGeo();
    //essais Segment
    testSegment();
    //essais Cercle
    testCercle();
    //essais Triangle
    testTriangle();
    //essais Polygone
    testPolygone();
    //essais FormeGeoComplexe 
    testFormeGeoComplexe();
}

Pch.h

#pragma once
#ifndef PCH_H
#define PCH_H

#include <cstring>
#include <cctype>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <vector>
#include "Exceptions.h"

#endif //PCH_H

Fonctions.h

#pragma once
#include "pch.h"

class Point;
class Vecteur2D;

/**
 * Récupère deux réels dans une chaîne
 *
 * */
void recupReels(double & nbx, double & nby, const char* s);

Vecteur2D PointsToVector(const Point & p1, const Point & p2);

Fonctions.cpp

#include "pch.h"
#include "Vecteur2D.h"
#include "Point.h"
#include "Fonctions.h"

/**
 * Récupère deux réels dans une chaîne
 *
 * */
void recupReels(double& nbx, double& nby, const char* s) {
    //copie string
     std::string  s_cp(s);
    //trim
    remove(s_cp.begin(), s_cp.end(), ' ');

    const char b = s_cp[0];
    const char e = s_cp[s_cp.size() - 1];
    //test présence parenthèses
    if (strncmp(&b, "(", 1) == 0 && strncmp(&e, ")", 1) == 0) {
        //chaînes des réels
         std::string  s_nbx("");
         std::string  s_nby("");
        //chaîne 0
         std::string  nulle("0");

        int i = 1;
        char c = s[i];
        //
        //PREMIER NOMBRE
        //nombre négatif ?
        bool negatif = false;
        if (strncmp(&c, "-", 1) == 0) { negatif = true; i++; }
        //charge la partie entière
        for (i; isdigit(s[i]); i++) {
            s_nbx.append(s, i, 1);
        }

        switch (s[i]) {
            //eventuelle partie décimale
        case '.':
            //partie entière existe pas ?
            if (s_nbx.size() == 0)s_nbx.append(nulle);

            s_nbx.append(s, i, 1);
            i++;
            //charge la partie décimale
            for (i; isdigit(s[i]); i++) {
                s_nbx.append(s, i, 1);
            }
            s_nbx.append(nulle);
            nbx = stod(s_nbx);
            if (negatif)nbx = -nbx;
            //
            //DEUXIEME NOMBRE
        case ',':
            //premier nombre existe pas ?
            if (s_nbx.size() == 0) throw Exceptions( std::string ("chaîne incorrecte 1"));
            i++;
            c = s[i];
            negatif = false;
            if (strncmp(&c, "-", 1) == 0) { negatif = true; i++; }
            //charge la partie entière
            for (i; isdigit(s[i]); i++) {
                s_nby.append(s, i, 1);
            }

            switch (s[i]) {
                //eventuelle partie décimale
            case '.':
                //partie entière existe pas ?
                if (s_nby.size() == 0)s_nby.append(nulle);

                s_nby.append(s, i, 1);
                i++;
                //charge la partie décimale
                for (i; isdigit(s[i]); i++) {
                    s_nby.append(s, i, 1);
                }
                s_nbx.append(nulle);
                nby = stod(s_nby);
                if (negatif)nby = -nby;
                break;
                //pas de partie décimale
            default:
                //partie entière existe pas ?
                if (s_nby.size() == 0)throw Exceptions( std::string ("chaîne incorrecte 2"));
                nby = stod(s_nby);
                if (negatif)nby = -nby;
            }
            break;
            //pas de deuxième nombre ni de decimale
        default:
            throw Exceptions( std::string ("chaîne incorrecte 3"));
            break;
        }
    }
    else throw Exceptions( std::string ("chaîne incorrecte 4"));
}

Vecteur2D PointsToVector(const Point & p1, const Point & p2) {
    Vecteur2D v(p1.getX() - p2.getX(), p1.getY() - p2.getY());
    return v;
}

Point.h

#pragma once
#include "pch.h"
#include "Vecteur2D.h"

class Point{
    private:
        double _x;
        double _y;
    public:

        //
        //CONSTRUCTEURS
        //

        Point(const double & x = 0, const double & y = 0):_x(x),_y(y){}

        /**
         * DONNEES : s respectant le format "(nombre réel,nombre réel)"
         * 
         * considère la présence d'une occurence de ',' et deux occurences de '.' dans la chaîne
         * */
        Point(const char* s);

        //
        //DESTRUCTEUR
        //

        virtual ~Point(){}

        //
        //OPERATEURS
        //

        /**
         * produit d'un point et d'un coefficient réel
         * 
         * */
        inline const Point operator *(const double& a)const {return Point(_x*a,_y*a);}

        /**
         * opposé d'un point
         * 
         * */
        inline const Point operator -()const {return Point(-_x,-_y);}

        //
        //GETTERS SETTERS
        //

        double getX()const { return _x; }

        double getY()const { return _y; }

        void setX(const double & x) { _x = x; }

        void setY(const double & y) { _y = y; }

        //
        //AUTRES
        //

        double distance(const Point & p)const {
            return sqrt(pow(p.getX()-_x,2) + pow(p.getY() - _y, 2));
        }

        static double distance(const Point & p1, const Point & p2) {
            return sqrt(pow(p2.getX() - p1.getX() , 2) + pow(p2.getY() - p1.getY(), 2));
        }

        /**
         * calcule et affecte de nouvelles coordonnées au point en fonction d'un vecteur (v)
         * */
        void translation(const Vecteur2D * v) {
            setX(_x + v->getX());
            setY(_y + v->getY());
        }

        /**
         * calcule et affecte de nouvelles coordonnées au point en fonction d'un point (p) et d'un coefficient (k)
         * */
        void homothetie(const Point & p, const double k) {
            setX(-((p.getX() - _x) / k) + p.getX());
            setY(-((p.getY() - _y) / k) + p.getY());
        }

        /**
         * calcule et affecte de nouvelles coordonnées au point en fonction d'un point (p) et d'un angle (a) en radian
         * */
        void rotation(const Point & p, const double & a) {
            setX(_x + distance(p) * cos(a));
            setY(_y + distance(p) * sin(a));
        }

        operator std:: string()const {
            std::ostringstream os;
            os << "( " << _x << " , " << _y << " )";
            return os.str();
        }

        const std::string toString()const{ return std::string("Point( ") + std::to_string(_x) + " , " + std::to_string(_y) + " )"; }

        friend std::ostream& operator << (std::ostream& os, const Point& u);
};


extern std::ostream& operator << (std::ostream& os, const Point& u);

Point.cpp

#include "pch.h"
#include "Point.h"
#include "Fonctions.h"

/**
 * DONNEES : s respectant le format "(nombre réel,nombre réel)"
 * considère la présence de 3 occurences de ',' dans la chaîne
 * */
Point::Point(const char* s){
    double nbx = 0, nby = 0;
    //récupère les réels dans la chaîne si possible
    try{
        recupReels(nbx, nby, s);
        //affecte les valeurs récupérées 
        _x = nbx;
        _y = nby;
    }
    catch (Exceptions & e) {
     std::string  s("Constructeur point: ");
        s = s + e.getMsg();
        e.setMsg(s);
        throw;
    }
}

std::ostream& operator << (std::ostream& os, const Point& u) {
    os << u.toString();
    return os;
}
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • 5
    You've managed to include literally everything *except* the offending function declaration and implementation. My crystal ball tells me you neglected to `inline` your implementation of `std::ostream& operator<<(std::ostream&, const Vector2D&)`, which I likewise wild-guess is implemented in your header `Vector2D.h`. – WhozCraig Jan 02 '20 at 16:44
  • When I said that it was just something stupid ... Thanks, my problem is solved but can you explain what " inline " changed ? – Pouillaude Alexis Jan 02 '20 at 16:56
  • Please do not edit resolution announcements into the question. Create an answer instead or detete the question please. – Yunnosch Dec 04 '20 at 11:29

0 Answers0