I have a "Foo.cpp" class and a "Bar.cpp" class. I want to overload the + operator on two arguments of Foo so that adding two Foos returns a Bar with a value that's the product of their values. The code looks like
//Foo.h
class Foo
{
public:
double foo_val;
Foo();
Foo(double);
};
Bar* operator+ (Foo&, Foo&)
.
//Foo.cpp
#include "Foo.h"
Foo::Foo(){foo_val = 0;}
Foo::Foo(double d){foo_val = d;}
Bar* operator+ (Foo& f1, Foo& f2){
return new Bar(f1.foo_val*f2.foo_val);
}
.
#include "Foo.h"
#include "Bar.h"
int main(){
Foo f1 = new Foo(4, 5);
Foo f2 = new Foo(1, 2);
Bar = f1+f2;
}
Bar is basically identical to Foo at the moment, and it has a constructor "Bar(double);"
It doesn't work at the moment, I think because Bar hasn't been defined before I try to make a new one. (The compiler error is "'Bar' does not name a type") However, I know I can't forward declare Bar at the top because that only works for pointers, whereas I'm trying to construct a new one. Is there some way to get this type of thing to work, or am I going about this totally wrong?
Thanks!
It's actually very simple. In Foo.h, you need to forward declare class Bar, so that the declaration of operator+ is valid:
class Bar;
class Foo
{
// ...
};
Bar* operator+ (Foo& f1, Foo& f2);
Then, in Foo.cpp, you need to include Bar.h since here you really need to know how Bar is declared:
#include "Foo.h"
#include "Bar.h"
// ...
Bar* operator+ (Foo& f1, Foo& f2)
{
// Now you can use Bar's constructor
return new Bar(...);
}
There are two options.
(1) Put
#include "Bar.h"
at the beginning of Foo.h. But if Bar.h already has #include "Foo.h", this will cause a circular dependency, so this is not a viable option.
(2) Put
class Bar;
in Foo.h, before the class definition of Foo.
Related
Suppose we have two classes Foo and Bar.
We can declare the Foo class and use its methods as following:
#include"foo.h"
Foo foo
class Bar{
Bar(){
foo.method1();
}
}
And we have the forward declaration, which stands to declare the Foo class as following:
#include"foo.h"
class Foo
class Bar{
Bar(){
}
}
What are the main differences between the two declartions, and when the forward declaration is prefered to the normal declaration?
In second case you don't need
#include"foo.h"
In forward declaration you just say compiler "There are Foo class somewhere. But I don't know how it look". So compiler can refer them but can't use them;
class Foo; //Forward declaration.
Foo* foo; // ok. Just pointer.
Foo foo;// error. Compiler can't instantiate object.
and
#include "foo.h"
Foo* foo; // ok. Just pointer.
Foo foo;// ok. Compiler can instantiate object.
So, in some case forward declaration can replace the inclusion of a header file.
I've been looking at examples for a component-based system and in some of the examples, I noticed the usage of class names outside of other classes like in the example below. What is the purpose/function of creating class Foo; and class Bar; and what is this called?
#pragma once
#include "foo.h"
#include "bar.h"
class Foo; // ???
class Bar; // ???
class Example
{
public:
Example() :
m_pExample(0) {}
virtual ~Example() {}
void something(const Foo& foo, const Bar& bar);
private:
Example* m_pExample;
};
It is called a forward declaration and declares class name as a valid but leaves out the definition. This mean that you can use the name as a type before the definition is encountered.
What are forward declarations in C++?
Those are called forward declaration
This help the compiler know that the type exists and it knows nothing about its size, members, and methods.
Therefore its a an incomplete type too.
Actually if you already have #include "foo.h" and #include "bar.h" (assuming the class definition of each class is already in its related .h file), I don't see why you should have the two class Foo; and class Bar; statement.
Usually the reason of putting the class Foo; and class Bar; is that you are going to provide the definition of the two classes yourself.
Example:
#pragma once
class Foo;
class Bar;
class Example
{
public:
Example() :
m_pExample(0) {}
virtual ~Example() {}
void something(const Foo& foo, const Bar& bar);
private:
Example* m_pExample;
};
class Foo
{
// Definition of Foo class goes here...
;
};
class Bar
{
// Definition of Bar class goes here...
;
};
Foo.h
class Foo{
private:
void printSpecialBar(Bar b);//syntax error: Identifier Bar
Foo.cpp
#include "Bar.h"
void Foo::printSpecialBar(Bar b)
{
//code goes here
}
Bar has the default constructor and one that takes two int's.
What is the problem with the syntax error? I tried using the scope resuloution operator Bar::Bar b but it didn't fix it.
A typical practice would be to put
class Bar;
in Foo.h, before any reference to Bar class, and include the actual class like
#include "Bar.h"
in Foo.cpp.
Since Foo.h references Bar, either use a forward declaration or #include "Bar.h" in Foo.h
So lets say I have a class called Foo and another called Bar. Bar contains an instance of Foo and I have a function in Foo that takes Bar as a parameter. However, when I #include "Bar.h" in Foo to allow Foo to see Bar I get this error on the lines that Bar is referenced on:
error: ISO C++ forbids declaration of 'Foo' with no type
I'm guessing this is because both of the classes rely on each other to compile. Is there any way to get around this?
EDIT: Both of these classes have header files where the other class is referenced inside a #ifndef declaration.
In Foo.h instead of including Bar.h you need to use the forward declaration class Bar;. Note that for this to work you need to take the parameter Bar as a reference or a pointer in Foo class.
class Foo;
class Bar
{
};
and
class Bar;
class Foo
{
};
But this might be a result of a wrong design!!
You'll need to use a forward declaration for at least one class:
Foo.h:
#include "Bar.h"
class Foo {
};
Bar.h:
class Bar;
#include "Foo.h"
class Bar {
};
Also beware that you cannot easily reference members of Bar in Foo.h (they're not declared). So any inlined members that need Bar will have to go in Foo.cpp (or .cc if you prefer). You also cannot have a Bar as a value member of Foo.
So:
class Bar {
Foo f; // OK. Compiler knows layout of Foo.
};
class Foo {
Bar b; // Nope. Compiler error, details of Bar's memory layout not known.
Bar *b; // Still OK.
};
This is especially tricky for templates. See the FAQ if you have troubles.
Use references or pointers for parameters and forward declarations. E.g.
//foo.h
class Bar;// the forward declaration
class Foo {
void myMethod(Bar*);
};
//foo.cpp
#include "bar.h"
void Foo::myMethod(Bar* bar){/* ... */}
//bar.h
#include "foo.h"
class Bar {
/*...*/
Foo foo;
};
This is a very noobish mistake, but I dont know whats happening here.
There are loads of pimpl examples but I dont understand why this isn't working (this was one of the examples more or less but I dont see the difference).
I have a very simple Pimpl example, but it wont work.
// Foo.hpp
#include <boost/scoped_ptr.hpp>
class Foo
{
struct Bar;
//boost::scoped_ptr<Bar> pImpl;
Bar* pImpl;
public:
Foo();
~Foo() {}
int returnValue();
private:
};
and
// Foo.cpp
#include "foo.hpp"
struct Foo::Bar
{
Bar() {}
~Bar() {}
int value;
};
Foo::Foo() : pImpl(new Bar())
{
pImpl->value = 7;
}
int Foo::returnValue() {
return *pImpl->value;
}
Compiling this gives me the error.
C2100: illegal indirection.
Thanks.
int returnValue() should be a member function:
// vvvvv
int Foo::returnValue() {
return pImpl->value; // no need to dereference, value isn't a pointer
}
You need to define your constructor, copy-constructor, copy assignment operator, and destructor after the implementation class has been defined. (Otherwise the implicit destructor is dangerous, and scoped_ptr won't let you do that):
// Foo.hpp
#include <boost/scoped_ptr.hpp>
class Foo
{
struct Bar;
boost::scoped_ptr<Bar> pImpl;
public:
Foo();
~Foo();
int returnValue(); // could be const (so should be)
private:
// just disable copying, like scoped_ptr
Foo(const Foo&); // not defined
Foo& operator=(const Foo&); // not defined
};
And:
// Foo.cpp
#include "foo.hpp"
struct Foo::Bar
{
int value;
};
Foo::Foo() :
pImpl(new Bar())
{
pImpl->value = 7;
}
Foo::~Foo()
{
// okay, Bar defined at this point; scoped_ptr can work
}
int Foo::returnValue()
{
return pImpl->value;
}
As an aside, you may have a problem using boost::scoped_ptr for a pImpl because your pImpl is forwardly declared and you may find that the class needs to be fully visible in order to call scoped_ptr's destructor (which deletes the underlying).
Some compilers will allow you to work around this by putting the body of your destructor in the compilation unit (the .cpp file) where the class is visible.
The simplest solution is that if your destructor has to be implemented anyway you may as well just use a raw pointer and have your destructor delete it. And if you want to use something from boost to help you, derive your outer class from boost::noncopyable. Otherwise ensure you handle copy-construction and assignment properly.
You can use shared_ptr to your pImpl. You can then copy your outer class around happily although they share the same underlying unless you overload the copy-constructor and assignment operator to do otherwise.