I thought that friend functions could access class variables as in how I try to do v.x, v.y, v.z in the << function. But it doesn't compile. It says it's unable to resolve identifier at those lines.
Also I'm trying to learn how to use namespaces. Even though I use the namespace vec in the implementation file I still have to include Vector:: before everything so what's the point?
Header file:
#ifndef VECTOR_H
#define VECTOR_H
namespace vec {
class Vector {
private:
double x, y, z;
public:
Vector(double, double, double);
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
}
#endif /* VECTOR_H */
.cpp file:
#include "Vector.h"
#include <iostream>
using namespace vec;
//Constructor
Vector::Vector(double x1 = 0, double y1 = 0, double z1 = 0) {
x = x1;
y = y1;
z = z1;
}
//Have also tried adding vec:: and Vector:: before operator<< here.
std::ostream& operator<<(std::ostream& out, const Vector& v) {
out<<"<"<<v.x<<", "<<v.y<<", "<<v.z<<">";
return out;
}
I believe part of the problem is that your vec.h doesn't have #include <iostream>, so the type std::ostream is unidentified in that file, and since that part is compiled before the vec.cpp main part, it fails to recognise your function.
You also need to put your operator<< into the namespace of vec. After all, you have asked for a friend function within that namespace.
With these two changes, your code compiles with gcc -Wall -Wextra -O2.
Your compile error may relative to below issues:
Default parameter only goes to function declaration not function
definition, you are doing the other way around.
Also, in Vector.cpp you should wrap up your class member function
definitions in namespace instead of calling using directive.
Try:
Vector.h
#include <iostream>
class Vector {
private:
double x, y, z;
public:
Vector(double x1 = 0, double y1 = 0, double z1 = 0);
^^ ^^ ^^
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
Vector.cpp
namespace vec
{
Vector::Vector(double x1, double y1, double z1)
:x(x1), y(y1), z(z1)
{
}
}
The friend std::ostream& operator<< declaration appears in namespace vec, so the definition should be prefixed by vec::. Your comment says you tried that - maybe you got confused by the other error messages billz documents, but you should reinstate vec::operator<< or surround it with namespace vec { ... }.
This creates an error like:
ns.cc: In function `int main()':
ns.cc:26: error: ambiguous overload for 'operator<<' in 'std::cout << w'
ns.cc:19: note: candidates are: std::ostream& operator<<(std::ostream&, const vec::Vec&)
ns.cc:10: note: std::ostream& vec::operator<<(std::ostream&, const vec::Vec&)
Related
This question already has answers here:
Separating class code into a header and cpp file
(8 answers)
Closed 4 months ago.
fyi I have looked at the other posts on this topic but I either didn't understand or didn't find my problem in them.
pretty much I am trying to put a class into a cpp and .h file, when I compile the code I get a warning saying "warning: inline function 'float map::get_mapped_value()' used but never defined.
And when I build the code I get an error saying undefined reference to 'map::get_mapped_value'
below are the code in each file
I thought I had all my includes correct, but maybe I am missing something, I am new to separating classes into seperate file, so any help would be greatly appreciated.
Thanks in advance, Dean.
map.cpp
#include "map.hpp"
#include <stdio.h>
#include <iostream>
using namespace std;
//------------------------Constructor definitions--------------------------
map::map(float Val_to_map_, float in_min_, float in_max_, float out_min_, float out_max_)
: Val_to_map(Val_to_map_)
, in_min(in_min_)
, in_max(in_max_)
, out_min(out_min_)
, out_max(out_max_)
{
}
//-------------------------------------------------------------------------
//------------------------Copy Constructor definitions---------------------
map::map(const map& mp)
: Val_to_map(mp.Val_to_map)
, in_min(mp.in_min)
, in_max(mp.in_max)
, out_min(mp.out_min)
, out_max(mp.out_max)
{
}
//-------------------------------------------------------------------------
//-----------------------equals function-------------------------------------
map& map::operator=(const map& mp)
{
if(this == &mp)
return (*this);
Val_to_map = mp.Val_to_map;
in_min = mp.in_min;
in_max = mp.in_max;
out_min = mp.out_min;
out_max = mp.out_max;
return (*this);
}
//---------------------------------------------------------------------------
//-------------------get function definitions--------------
inline float map::get_mapped_value()
{
return (float((Val_to_map - in_min) * (out_max - out_min) / (in_max - in_min) + out_min));
}
//-----------------------------------------------------------
//-------------------set function definitions----------------
inline void map::set_Val_to_map(float _Val_to_map)
{
Val_to_map = _Val_to_map;
}
inline void map::set_in_min(float _in_min)
{
in_min = _in_min;
}
inline void map::set_in_max(float _in_max)
{
in_max = _in_max;
}
inline void map::set_out_min(float _out_min)
{
out_min = _out_min;
}
inline void map::set_out_max(float _out_max)
{
out_max = _out_max;
}
//-----------------------------------------------------------
map.h
#ifndef MAP_HPP
#define MAP_HPP
using namespace std;
class map
{
public:
//----------------Special Member functions-----------------
map(float Val_to_map_, float in_min_, float in_max_, float out_min_, float out_max_); // accepted arguments
map(const map& m); // copy constructor
map& operator=(const map& m); // Equals function
~map()
{
} // destructor
//---------------------------------------------------------
//-----------------get functions-----------------
inline float get_mapped_value();
//------------------------------------------------
//-----------------set functions-----------------
inline void set_Val_to_map(float Val_to_map);
inline void set_in_min(float in_min);
inline void set_in_max(float in_max);
inline void set_out_min(float out_min);
inline void set_out_max(float out_max);
//------------------------------------------------
private:
float Val_to_map;
float in_min; // min Vref
float in_max; // max Vref
float out_min; // min output voltage from psu
float out_max; // max output voltage from psu
};
#endif // MAP_HPP
main.cpp
main(){
map voltage(1, map_in_min, map_in_max, map_out_min, map_out_max);
cout << "Mapped val: " << voltage.get_mapped_value() << endl;
}
You declared the function get_mapped_value as an inline function
inline float get_mapped_value();
So its definition shall be in each compilation unit where it is used.
The simplest way to resolve the problem is to include the function definition either directly in the class definition where it is declared or in the header where the class definition is present.
The following code generates errors LNK2005 & LNK1169 on Visual Studio 2019.
LNK2005: "void__cdecl OverloadingPlus(void)" (?OverloadingPlus##YAXXZ) already defined in main.obj
LNK1169: one or more multiply defined symbols found
I reached this point by following a course on Udemy, where the instructor seems to have no problems with it.
Similar questions seem to be related to using global variables, defining functions in the header file, not using #ifndef guards... but as far as I can tell, that doesn't seem to be the case.
This problem started appearing only after the operator+ overload was included, but the operator<< doesn't trigger any errors, even though they have been declared and defined in the same manner.
Interestingly enough, if I remove any reference to OverloadingPlus.h file, and add #include Complex.h to main.cpp, the problem goes away.
I fail to see how including Complex.h in OverloadingPlus.h is contributing to a multiple definition of the operator+ exclusively, even though it is only included once in the entire project and the definitions are implemented in Complex.cpp and not in the header file, as pointed out in answers to similar problems.
Also tried surrounding the content of OverloadingPlus.h with an #ifndef statement just to make sure it is only used once which did not change a thing.
I attempted to declare a diferent operator+ overload inside the class (you can see it commented out), but it produces the same errors.
Commented all references to any other files trying to make sure Complex definitions are only included once. Didn't help either.
The code is the following:
main.cpp
//#include "OverloadingAssignmentOperator.h"
//#include "OverloadingLeftBitShiftOperator.h"
//#include "ComplexNumberClass.h"
#include "OverloadingPlus.h"
int main() {
//OverloadingAssignmentOperator();
//OverloadingLeftBitShiftOperator();
//ComplexNumberClass();
OverloadingPlus();
return 0;
}
OverloadingPlus.h
#ifndef OVERLOADING_PLUS_H
#define OVERLOADING_PLUS_H
#include "Complex.hpp"
using namespace complex;
void OverloadingPlus() {
Complex c1(1, 4);
Complex c2(3, 2);
std::cout << c1 + c2 << std::endl;
}
#endif
Complex.hpp
#ifndef COMPLEX_HPP
#define COMPLEX_HPP
#include <iostream>
namespace complex {
class Complex {
private:
double real;
double imaginary;
public:
Complex();
Complex(double, double);
Complex(const Complex&);
const Complex& operator=(const Complex& other);
//const Complex operator+(const Complex& r);
double getReal() const { return real; }
double getImaginary() const { return imaginary; }
};
Complex operator+(const Complex& l, const Complex& r);
std::ostream& operator<<(std::ostream& out, const Complex& c);
}
#endif // !__COMPLEX_HPP__
Complex.cpp
#include "Complex.hpp"
namespace complex {
Complex::Complex() : real(0), imaginary(0) {}
Complex::Complex(double r, double i) : real(r), imaginary(i) {}
Complex::Complex(const Complex& other) {
std::cout << "Copy constructor..." << std::endl;
real = other.real;
imaginary = other.imaginary;
}
const Complex& Complex::operator=(const Complex& other) {
real = other.real;
imaginary = other.imaginary;
return *this;
}
//const Complex Complex::operator+(const Complex& r) {
// return Complex(real + r.getReal(), imaginary + r.getImaginary());
//}
//
Complex operator+(const Complex& l, const Complex& r) {
return Complex(l.getReal()+r.getReal(), l.getImaginary()+r.getImaginary());
}
std::ostream& operator<<(std::ostream& out, const Complex& c) {
out << "(" << c.getReal() << "," << c.getImaginary() << ")";
return out;
}
}
The issue seems to be related to VS2019. Renaming the file to something different, rebuilding the project and renaming the file back to its original name fixed the issue.
While using inline as others suggested did circumvent the issue, it does not solve this specific problem as the conflicting file was not being included multiple times.
You forgot to "inline" your OverloadingPlus.
inline void OverloadingPlus() {
Complex c1(1, 4);
Complex c2(3, 2);
std::cout << c1 + c2 << std::endl;
}
should make the linker error go away.
What probably happened is: You have included "OverloadingPlus.h" in more than one compilation unit (although you failed to provide all instances of your #include in your question).
Every time you include "OverloadingPlus.h" in one of your .cpp files, you add another definition for void OverloadingPlus to your program. The linker detects this and cannot decide on "the right one" and so gives an error.
I have a class called Vector3 in a header file called Vector.h. Everything is fine until I include this file in another header file. IntelliSense then marks every function that uses Vector3 (as a parameter or return value) as an error: Error: "Variable Vector3"" is not a type name. I can't explain why this happens at all. I created a new test project and included Vector.h again, but in this new project everything compiles fine. Here's the code of the file:
#ifndef VECTOR_H_
#define VECTOR_H_
#include <math.h>
class Vector3
{
public:
double x, y, z;
Vector3();
Vector3(double x, double y, double z);
void normalize();
};
Vector3 normalize(Vector3 v);
Vector3 cross(Vector3 a, Vector3 b);
Vector3 min(Vector3 a, Vector3 b);
Vector3 max(Vector3 a, Vector3 b);
#endif
Update:
I realised that there only is an Error if I include windows.h before Vector.h. If I dont include windows.h or if I include it after vector.h I dont get any error.
I've been trying to create a class cartesian which objects are 2 points on the a cartesian point (int or double). Then I want to overload <<. I get the error message :
Undefined symbols for architecture x86_64:
"cartesian<double, int>::cartesian(double, int)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I dont understand where is My mistake.
THE HEADER
#include <iostream>
using namespace std;
template <class first, class second>
class cartesian
{
public:
cartesian(first, second);
//double getslope(cartesian &obj1, cartesian &obj2);
friend ostream& operator<< (ostream &out, cartesian &cPoint);
private:
first x;
second y;
};
THE CPP file
#include "cartesian.h"
#include <iostream>
using namespace std;
template<class first,class second>
cartesian<first, second>::cartesian(first a, second b)
:x(a), y(b)
{}
/*
// between obj1 and obj2
template<class first,class second>
double cartesian<first, second>::getslope(cartesian &obj1, cartesian &obj2){
return ((obj2.y-obj1.y)/(obj2.x-obj1.y));
}
*/
template<class first,class second>
ostream& operator<< (ostream &out,const cartesian<first, second> &cPoint)
{
// Since operator<< is a friend of the Point class, we can access
// Point's members directly.
out << "(" << cPoint.x << ", " <<
cPoint.y << ")";
return out;
}
THE MAIN
#include <iostream>
#include "cartesian.h"
using namespace std;
int main()
{
cartesian<double, int> ob11(3.4, 6);
return 0;
}
You need to put the implementation in the header file or in a file included by the header. The compiler needs access to the code in order to "build" the cartesian<double, int> specialization you require in main.
For example, here we put the constructor's implementation in the class declaration:
template <class first, class second>
class cartesian
{
public:
cartesian(first, second) :x(a), y(b) {}
};
It doesn't have to go inside the class declaration itself, but the code must be accessible from the header file.
Hey i'm getting this odd error when I leave the namespace sf{ declaration in the later code:
1>c:\libraries and headers\sfml\sfml-1.6-sdk-windows-vc2008\sfml-1.6\include\sfml\graphics\body.h(70): error C2989: 'sf::Body' : class template has already been declared as a non-class template
1>c:\libraries and headers\sfml\sfml-1.6-sdk-windows-vc2008\sfml-1.6\include\sfml\graphics\body.h(11): error C3856: 'sf': class is not a class template
The code worked fine when it wasn't a template class for the past 3 weeks, With the same sf::Body class name; i just recently changed it to make it more flexible. Can i not declare a template class inside a namespace or what?
Here's the code:
#include <SFML/Graphics.hpp>
#include <vector>
#include <math.h>
#include <cmath>
namespace sf{ //when i take this out and the closing bracket the code runs fine
template<typename drawable>
class Body : public sf::Drawable{
private:
sf::Vector2f MoveVal;
std::vector<drawable> Drawables;
public:
Body(const Vector2f& Position = Vector2f(0, 0), const Vector2f& Scale = Vector2f(1, 1), float Rotation = 0.f, const Color& Col = Color(255, 255, 255, 255)){
SetPosition(Position);
SetScale(Scale);
SetRotation(Rotation);
SetColor(Col);};
// Overide Drawable Functions To Detect any Movement
void SetX(float X){
MoveVal.x += X - GetPosition().x;
Drawable::SetX(X);};
void SetY(float Y){
MoveVal.y += Y - GetPosition().y;
Drawable::SetY(Y);};
// Regular Functions
void AddObject(drawable& Object){
Object.Move(GetX(),GetY());
Drawables.push_back(Object);};
void DestroyObject(unsigned short Index){
Drawables.erase(Drawables.begin()+Index);};
void Clear(){
Drawables.clear();};
drawable& GetObject(unsigned short index)
{return Drawables[index];};
unsigned int GetNumbObjects()
{return Drawables.size();};
void Draw(sf::RenderTarget& target){
for(unsigned short I=0; I<Drawables.size(); I++){
//Body offset
Drawables[I].SetPosition(
Drawables[I].GetPosition().x + MoveVal.x,
Drawables[I].GetPosition().y + MoveVal.y);
} // TODO: add tint based on overall Body Color
target.Draw(*this);
//Reset all the Change Values
MoveVal.x=0;
MoveVal.y=0;
};
void Render(sf::RenderTarget& target) const{
for(int I=0; I< Drawables.size(); I++)
Drawables[I].Draw(target);
};
};// Body Class
} //namespace sf
Ok found the problem:
In a previously included header file: Shape.hpp I declare Body as a friend with the following syntax:
friend class Body;
Which apparently makes the compiler assume Body is not a template (no template indication is made)
The correct syntax was:
template <typename drawable>
friend class Body;
Because now the compiler understands Body as a template class
The two most likely candidates based on your information are that Graphics.hpp has mismatched { } or that you had a forward declaration of class Body without marking it a template.
sf::Body is a name that seems to be already taken (for a class whereas you're declaring a template). Are you sure you want to put your code in the sf namespace? It's more customary to use one's own namespaces rather than those of the libraries they use.