I encountered some issues while working on friend functions. I want to use a friend function that uses two different classes in parameters. Here is the sample of code:
ObjectA.h:
#ifndef OBJECTA_H_
#define OBJECTA_H_
#include "ObjectB.h"
#include <iostream>
using namespace std;
class ObjectA {
private:
friend void friendFunction(ObjectA &,ObjectB &);
public:
ObjectA();
virtual ~ObjectA();
};
#endif /* OBJECTA_H_ */
ObjectB.h:
#ifndef OBJECTB_H_
#define OBJECTB_H_
#include <iostream>
using namespace std;
#include "ObjectA.h"
class ObjectB {
private:
friend void friendFunction(ObjectA &, ObjectB &);
public:
ObjectB();
virtual ~ObjectB();
};
#endif /* OBJECTB_H_ */
Both .cpp files for ObjectA and ObjectB are empty (empty constructor and destructor). Here is the main .cpp file:
#include <iostream>
using namespace std;
#include "ObjectA.h"
#include "ObjectB.h"
void friendFunction(ObjectA &objA, ObjectB &objB){
cout << "HIIIIIIIIIII";
}
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
This all thing sends me the following error :
'ObjectA' has not been declared
And this error is pointing to this line in the ObjectB.h :
friend void friendFunction(ObjectA &, ObjectB &);
As you can see, the ObjectA.h file has been included in the ObjectB.h file. So I don't know where my error come from.
Maybe I'm using friend function in a wrong way ?
Thank you guys !
In ObjectA.h, replace:
#include "ObjectB.h"
with:
class ObjectB;
Make the corresponding change in ObjectB.h.
What's happening is that main.cpp is including ObjectA.h. Before declaring the ObjectA class, ObjectA.h includes ObjectB.h. When ObjectB.h tries to include ObjectA.h again, the #ifndef OBJECTA_H_ test fails, meaning the ObjectA class isn't declared when the friend function is declared, leading to the error.
You can break this loop in your specific case by using a forward class declaration instead of #include.
Baybe using template function instead? But this way you will break encapsulation.
class A{
private:
template<typename T, typename B>
friend void friendFunc( const T&, const B&);
int m_a;
};
template<typename A, typename B>
void friendFunc( const A& a, const B& b){
std::cout << a.m_a << std::endl;
}
int main(int argc, char **argv) {
friendFunc<A, int>(A(), int(3));
return 0;
}
Related
Im trying to define a class friend function outside the namespace like this:
namespace A{
class window{
private:
int a;
friend void f(window);
};
}
void f(A::window rhs){
cout << rhs.a << endl;
}
Im getting an error said that there is ambiguity. and there is two candidates void A::f(A::window); and void f(A::window). So my question is :
1) How to make the global function void f(A::window rhs) a friend of the class A::window.
EDIT: (After reading the answers)
2) why do I need to qualify the member function f inside window class to be global by doing ::f(window) ?
3) why do I need to predeclare the function f(A::window) in this particular case, whereas when the class is not a defined inside a namespace it's okey for the function to be declared after the function is declared a friend.
As well as adding a :: you need to forward declare it, e.g.:
namespace A { class window; }
void f(A::window);
namespace A{
class window{
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs){
std::cout << rhs.a << std::endl;
}
Note that for this forward declaration to work you need to forward declare the class too!
This should do it: you need forward declares to make it clear f is in the global namespace (and not file static):
#include <string>
#include <iostream>
using namespace std;
////// forward declare magic:
namespace A{ class window; }
void f(A::window rhs);
//////
namespace A {
class window {
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs) {
cout << rhs.a << endl;
}
int main()
{
}
Using ::, you can also friend a class from the outer wrapping namespace:
namespace Na {
class A;
namespace Nb {
class B {
...
friend class ::Na::A;
};
Without going from global top as 'friend class Na::A', the search will be done in Na::Nb::Na only.
I am trying to use forward declarations in header files to reduce the number of #include used and hence reduce dependencies when users include my header file.
However, I am unable to forward declare where namespaces are used. See example below.
File a.hpp:
#ifndef __A_HPP__
#define __A_HPP__
namespace ns1 {
class a {
public:
a(const char* const msg);
void talk() const;
private:
const char* const msg_;
};
}
#endif //__A_HPP__
File a.cpp:
#include <iostream>
#include "a.hpp"
using namespace ns1;
a::a(const char* const msg) : msg_(msg) {}
void a::talk() const {
std::cout << msg_ << std::endl;
}
File consumer.hpp:
#ifndef __CONSUMER_HPP__
#define __CONSUMER_HPP__
// How can I forward declare a class which uses a namespace
//doing this below results in error C2653: 'ns1' : is not a class or namespace name
// Works with no namespace or if I use using namespace ns1 in header file
// but I am trying to reduce any dependencies in this header file
class ns1::a;
class consumer
{
public:
consumer(const char* const text) : a_(text) {}
void chat() const;
private:
a& a_;
};
#endif // __CONSUMER_HPP__
Implementation file consumer.cpp:
#include "consumer.hpp"
#include "a.hpp"
consumer::consumer(const char* const text) : a_(text) {}
void consumer::chat() const {
a_.talk();
}
Test file main.cpp:
#include "consumer.hpp"
int main() {
consumer c("My message");
c.chat();
return 0;
}
UPDATE:
Here is my very contrived working code using the answer below.
File a.hpp:
#ifndef A_HPP__
#define A_HPP__
#include <string>
namespace ns1 {
class a {
public:
void set_message(const std::string& msg);
void talk() const;
private:
std::string msg_;
};
} //namespace
#endif //A_HPP__
File a.cpp:
#include <iostream>
#include "a.hpp"
void ns1::a::set_message(const std::string& msg) {
msg_ = msg;
}
void ns1::a::talk() const {
std::cout << msg_ << std::endl;
}
File consumer.hpp:
#ifndef CONSUMER_HPP__
#define CONSUMER_HPP__
namespace ns1
{
class a;
}
class consumer
{
public:
consumer(const char* text);
~consumer();
void chat() const;
private:
ns1::a* a_;
};
#endif // CONSUMER_HPP__
File consumer.cpp:
#include "a.hpp"
#include "consumer.hpp"
consumer::consumer(const char* text) {
a_ = new ns1::a;
a_->set_message(text);
}
consumer::~consumer() {
delete a_;
}
void consumer::chat() const {
a_->talk();
}
File main.cpp:
#include "consumer.hpp"
int main() {
consumer c("My message");
c.chat();
return 0;
}
To forward declare class type a in a namespace ns1:
namespace ns1
{
class a;
}
To forward declare a type in multiple level of namespaces:
namespace ns1
{
namespace ns2
{
//....
namespace nsN
{
class a;
}
//....
}
}
Your are using a a member of consumer which means it needs concrete type, your forward declaration won't work for this case.
For nested namespaces, since C++17, you can do
namespace ns1::ns2::nsN
{
class a;
}
Apart to forward-declare the class from within its namespace (as #billz says), remember to either use (prepend) that namespace when referring to the forward-declared class, or add a using clause:
// B.h
namespace Y { class A; } // full declaration of
// class A elsewhere
namespace X {
using Y::A; // <------------- [!]
class B {
A* a; // Y::A
};
}
Ref: Namespaces and Forward Class Declarations
I already saw many answers how to create (e.g.) A class with an object B b and a B class with an object A a
like:
B:
class A;
class B{
A& a;
};
A:
class A{
B b;
};
but if I want to call a function from A in B I got: Invalid use of incomplete type 'class A'
What can I do? I think I know why the compiler say that, but I don't know how to fix it.
Here my latest Code:
Main.cpp:
#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
MainClass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print() { sub.print(); }
void printTest() { std::cout << "test" << std::endl; }
};
#endif
SubClass.h:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print() { main->printTest(); }
protected:
private:
};
#endif
The main problem with your code is that the definition of MainClass and SubClass are mutually dependent, therefore the use of the header guards will forbid the inclusion of both header files in the same translation unit (i.e. the union of a cpp file and the all the header files included.)
The forward declaration of class MainClass in subclass.h could solve this problem, since the SubClass::main is a pointer (check the PIMPL idiom), but since you have included the implementation of the class methods in the in the header files, the compiler fails when the SubClass::print() method makes a reference to MainClass::printTest() because it knows nothing about the class MainClass except the fact that it is defined somewhere else.
On the other hand, changing the forward declaration with the explicit inclusion of mainclass.h in subclass.h is not a solution, because of the header guards, as said above.
The simple solution is to split the declaration and the implementation of you classes in .h and .cpp files. If you do so, the compiler will work on multiple translation units: one for the mainclass.cpp, one for the subclass.cpp and one for the main.cpp. When processing the subclass.cpp translation unit, the compiler will be able to include the file mainclass.h and will have the complete definition of MainClass to "see" that a MainClass::printTest() method exists.
Here is the mainclass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print();
void printTest();
};
#endif
the mainclass.cpp file:
#include <iostream>
#include "mainclass.h"
void MainClass::print()
{
sub.print();
}
void MainClass::printTest()
{
std::cout << "test" << std::endl;
}
The subclass.h file:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
};
#endif
the subclass.cpp:
#include "mainclass.h"
//#include "subclass.h" // already included with the previous line
void SubClass::print()
{
main->printTest();
}
and finally the main.cpp:
#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
This will compile and will apparently work, because it will print the string "test" even if the main pointer is not initialized, and points to an undefined memory area.
This happens because the printTest method does nothing but producing a side effect, i.e. printing on screen. Indeed it does not access to any data member of the MainClass through the this pointer, and therefore you have no memory access violation. Indeed, invoking a method on a not instantiated pointer is an undefined behavior, so it would be better to avoid it, as well as cyclic dependencies.
You can't call a function (MainClass::printTest) that does not exist yet.
You can declare the function inside the SubClass, but define it after you have the MainClass definition.
#include <iostream>
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
protected:
private:
};
class MainClass
{
SubClass sub;
public:
void print() { sub.print(); }
void printTest() { std::cout << "test" << std::endl; }
};
void SubClass::print() { main->printTest(); }
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
Avoid creating function bodies in H files and put the function body into Cpp file.
MainClass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass {
SubClass sub;
public:
void print();
void printTest();
};
#endif
MainClass.cpp:
#include <iostream>
#include "mainclass.h"
void MainClass :: print () { sub.print(); }
void MainClass :: printTest() {std::cout << "test" << std::endl; }
SubClass.h
#ifndef SUBCLASS_H
#define SUBCLASS_H
#include "mainclass.h"
class SubClass
{
MainClass* main;
public:
void print();
protected:
private:
};
#endif
SubClass.cpp
#include "mainclass.h"
#include "subclass.h"
void SubClass::print ()
{
main->printTest();
}
you can actually #include "mainclass.h" in your subclass.h because it is guarded by #ifdef
You have a design problem:-
How come in SubClass.h compiler will know class MainClass has a method printTest so that it can link to it as you did not included the header file for the definition of MainClass
Another problem is you can not even include MainClass.h in SubClass.h because you are reference to SubClass sub; in it.
MainClass* main; pointer main never initialized and hence this statement void print() { main->printTest(); } is also wrong here.
I have a class A with the following declaration (A.h file):
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#endif
and a class B deriving from that class (B.h file):
#ifndef __B_DEFINED__
#define __B_DEFINED__
#include <iostream>
#include "A.h"
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
So far, so good. My issue is that the function A::doThat() uses B::doThis():
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
Usually, the circular dependency would not be an issue because I would just define A::doThat() in the .cpp file. In my case however, doThat is a template function so I can't do that.
Here are the solutions I have envisioned so far:
Defining the template function A::doThat() in a .cpp file. The issue with that is that I need to instantiate explicitly all the calls with various template arguments (there might be many in the real case).
After the declaration of the A class in A.h, add #include "B.h" and then define the A::doThat() function. This works fine in visual studio but g++ does not like it.
Is there a neat way to solve this problem?
EDIT: In the real case, there is not just one child class B, but several (B, C, D, etc.) The function A::doThat() depends on all of them. The function B::doThis() is also templated.
A default template parameter for the B class could work:
#include <iostream>
// include A.h
class B;
class A
{
public:
template<typename T, typename U = B> inline void doThat() const
{
U b; b.doThis();
}
};
// include B.h
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
// main
int main()
{
A a;
a.doThat<int>();
}
Usually the best way to allow a parent to call a child function is to declare the function as a pure virtual function in the parent and override it in the children.
#include <iostream>
class A
{
public:
virtual ~A() = default;
template<typename T> inline void doThat() const
{
// do some other stuff
doThis();
}
virtual void doThis() const = 0; // pure virtual function
};
class B: public A
{
public:
void doThis() const override
{
std::cout << "do this!" << std::endl;
}
};
int main()
{
B b;
A* ap = &b;
ap->doThat<int>();
}
The following does work with g++:
File A.h:
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#include "B.h"
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
#endif
File B.h:
#include <iostream>
#include "A.h"
// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
File test_A.cpp:
// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.
int main() {
A a;
a.doThat<int>();
}
File test_B.cpp:
// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.
int main() {
B b;
b.doThat<int>();
b.doThis();
}
Alternative Idea:
I do not know whether you (or some coding conventions) insist on separate header files for each class, but if not the following should work:
You can put the definitions of class A and class B and of the member function template A::doThat<typename>() (in this order) together in one header file AandB.h (or whatever name you like).
This cries for polymorphism. There are two options using polymorphism:
Dynamic polymorphism, i.e. make A an abstract base class and call doThis() virtually:
struct A
{
virtual void do_this() const = 0;
template<typename T>
void doThat() const { doThis(); }
};
struct B : A
{
void doThis() const override { /* ... */ }
};
Of course, this only works if doThis() is not templated. If you need that, you could use
Static polymorphism, i.e. CRTP, when
template<typename Derived>
struct A
{
template<typename T>
void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); }
};
struct B : A<B>
{
template<typename T>
void doThis() const { /* ... */ }
};
If (as in your example code) B::doThis() is not called for the same object, but for some temporary, you could
template<typename typeB>
struct A
{
template<typename T>
void doThat() const { typeB b; b.template doThis<T>(); }
};
In my C++ program I have separate .h and .cpp files and everything is working so far except when I want to use a base class constructor for a derived class. It is working but only if I put the function definition if the class deceleration.
Here's the working code for the .h file.
#include <iostream>
using namespace std;
class property
{
public:
property();
property(const property & src);
property(int src);
~property();
virtual int disp() const = 0;
int get_ownable();
private:
protected:
int ownable;
};
class rr : public property
{
public:
rr();
rr(const rr & src);
rr(int src):property(src)
{cout << "\nderived class was called\n";};
~rr();
virtual int disp() const;
private:
protected:
};
The imp.cpp (implementation) file is
#include "head.h"
#include <iostream>
using namespace std;
//property class implimentations
property::property()
{
ownable = 0;
}
property::property(const property & src)
{
ownable = src.ownable;
}
property::property(int src)
{
ownable = src;
cout << "\nparent class called\n";
}
property::~property()
{
}
int property::get_ownable()
{
return ownable;
}
rr::rr()
{}
rr::rr(const rr & src)
{
ownable = src.ownable;
}
/*
rr::rr(int src):property(src)
{
cout << "\nderived class was called\n";
}
*/
rr::~rr()
{
}
int rr::disp() const
{
}
There is other code but it is working fine and not connected to this. The output is
parent class called
derived class was called
So that works just fine but if I un-comment out the function in the .imp file and remove the declaration in the .h
rr(int src):property(src);
I get the error
head.h: IN constructor 'rr::rr(int)':
head.h 113: error: expeted '{' at end of input
imp.cpp: at global scope:
imp.cpp:348:error: redefiniton of 'rr::rr(int);
head.h.113: error: 'rr::rr(int); previousle defined here
All the examples I can find on line of how to do this do it with all the functions defined in the class declaration. I can't find any examples of how to do it with 2 files. Can anyone tell me how to define the base class constructor call in a separate file?
I am on a Linux system using g++ compiler.
Like this
BaseClass.h
#pragma once
class BaseClass {
public:
BaseClass(int a);
private:
int a_private;
};
BaseClass.cpp
#include "BaseClass.h"
#include <iostream>
using std::cout;
using std::endl;
BaseClass::BaseClass(int a) {
cout << "Base class constructor called" << endl;
this->a_private = a;
}
Derived.h
#pragma once
#include "BaseClass.h"
class Derived : public BaseClass {
public:
Derived(int a);
private:
int a_private;
};
Derived.cpp
#include "Derived.h"
#include <iostream>
using std::cout;
using std::endl;
Derived::Derived(int a) : BaseClass(a) {
cout << "Derived class constructor called" << endl;
this->a_private = a;
}
main.cpp
#include "BaseClass.h"
#include "Derived.h"
int main() {
Derived d(2);
return 0;
}
Compiling with the command
g++ main.cpp Derived.cpp BaseClass.cpp and running will result in the following output
Base class constructor called
Derived class constructor called
As mentioned in the comments (credits #IgorTandetnik), initializer lists should be used only in the implementation file. Not in the header file (provided the class is not templated).