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;
}