Use friend function from another cpp - c++

I need to define a function in my .hpp file, declare it in my .cpp file and then use it in a second .cpp file that includes the first one.
My problem is that when I do all this, I get the error: "example" was not declared in this scope.
I don't understand what I'm doing wrong, can someone please help me?
base.hpp
class Base {
public:
static size_t b;
Base() {};
friend Base exemple(uint64_t value);
};
base.cpp
Base exemple(size_t value)
{
Base res;
Base::b = value;
return res;
}
in the main of my second cpp (stack.cpp)
exemple(3);

Related

How to define a private member function only in cpp

So consider I have a class with a private member variable and a private function which I do not want to define in the header file, because I want to "hide" it from the user.
How can I make this? I can not access the private variable without the declaration of the function in the header.
So what works is something like this:
// header file
class Testclass {
public:
// ...
private:
const int m_i;
void func() const;
}
// cpp file
#include "TestClass.h"
Testclass::func() const {
int j = m_i; //access to a private member variable
}
// ...
But I want something like this:
// header file
class Testclass{
public:
//...
private:
const int m_i;
}
// cpp file
#include "TestClass.h"
Testclass::func() const {
int j = m_i; //access to a private member variable
}
// ...
Which possibilities do I have? I read something about the PIMPL Idiom, but I am not sure if this is what I want, since it looks a bit cumbersome coding-wise.
You can have non-member helper functions in the cpp file, that the class members can use. However, they would have to pass the private variable as a parameter.
// header file
class Testclass{
public:
//...
private:
const int m_i;
}
// cpp file
#include "TestClass.h"
void func(int m_i) {
int j = m_i; //private member variable supplied by caller
}
// ...
Normally one achieves this through the PIMPL (Pointer to IMPLementation) idiom. In your header file you have:
class MainClass
{
public:
void public_function();
private:
class Impl;
Impl* impl;
};
Note that the header file does not contain the definition of the Impl class, only its declaration.
You then define that class in your cpp file and forward the calls from your public interface to the functions of the impl class:
class MainClass::Impl
{
void actualfunc()
{
//do useful stuff here
}
};
void MainClass::public_function()
{
return impl->actualfunc();
}
Apart from your indended hiding of unwanted members from your class users, the PIMPL idiom provides the additional benefit that if no changes are made to the interface of the class, the users of the class need not be recompiled.

Using a class created in a cpp file as an argument type in a header file

I am going through some code which is a little un-organized.
I would like to use a class created in a cpp file used as an argument type in its header file. I know the class needs to be defined in the header but I am currently looking for a short approach here for now. This is what I have
filename: foo.cpp
class bar {
}
Now the header
filename: foo.h
class teacher {
public:
void dosomething(bar b) { ///<-----Incomplete type.
b.work(); ///
}
}
I tried declaring a prototype inside the header this way
class foo;
class teacher {
public:
void dosomething(bar b) {
b.work(); ///Error no method work for incomplete type.
}
}
What would be the simplest way to fix this issue apart from moving the bar class to the header file
You can forward-declare the type bar in the header assuming you do nothing that relies on it being a complete type. For example, this won't work:
// foo.hpp
class bar;
class teacher {
public:
void dosomething(bar b) {
// Will fail, bar is not complete:
b.work();
}
};
But this will:
// foo.hpp
class bar;
class teacher {
public:
void dosomething(bar b);
};
// foo.cpp
class bar {
public:
void work() {}
};
void teacher::dosomething(bar b) {
b.work();
}
However, I would advise instead to create a bar.hpp file with the definition of the bar type and #include it into foo.hpp.
Consider, for example, that any code (other than foo.cpp) that includes foo.hpp will be unable to invoke teacher::dosomething(bar), since it won't have any definition for bar.
I think it will be better like this :
File : bar.hh
class bar
{
...
}
File : foo.hh
#include "bar.hh"
class teacher
{
public:
void dosomething(bar b)
{
b.work();
}
}

Is it possible to call a private constructor from a static method defined in the cpp?

A C++ n00b question. Is it possible to call a private constructor from a static method defined in the cpp? I'd like to keep methods out of the header file if possible -- I figure there should be a way to do this. I'm getting an error when attempting this:
"cannot access private member declared in class SomeClass"
/////////////////
// SomeClass.h //
/////////////////
class SomeClass {
public:
static SomeClass SomeMethod();
private:
SomeClass(int i);
}
///////////////////
// SomeClass.cpp //
///////////////////
static SomeClass OSImplementation() {
return SomeClass(0);
};
// calls implementation
SomeClass SomeClass::SomeMethod() {
return OSImplementation();
}
You can make OSImplementation a friend method.
Or you can make OSImplementation a static method within the class (but that has to be declared in the header).
Or, probably the most common way to do this, is to have an internal implementation class, like this:
class SomeClass {
public:
//...
private:
struct Impl;
Impl* intern;
};
In your cpp file, you declare struct SomeClass::Impl.
In your constructor, create the SomeClass::Impl instance. Delete it in the destructor. And implement the copy-constructor and the assignment operator!
This is called the PIMPL (pointer to implementation) idiom (Wikipedia, c2.com). It's used a lot in big projects like Qt.
Yes, it is possible, by making the OSImplementation() friend of SomeClass. Next example compiles without warnings and errors using g++ 4.6.1 :
#include <iostream>
// declare in hpp
class SomeClass {
friend SomeClass OSImplementation();
public:
static SomeClass SomeMethod();
void foo();
private:
SomeClass(int);
};
int main()
{
auto obj = SomeClass::SomeMethod();
obj.foo();
}
// define in cpp
SomeClass SomeClass::SomeMethod(){
return SomeClass( 5 );
}
SomeClass::SomeClass(int){
}
void SomeClass::foo(){
std::cout<<"foo"<<std::endl;
}
SomeClass OSImplementation()
{
return SomeClass::SomeMethod();
}

Does the friend function have to be in the same file?

I am actually testing a file and I have a situation, where I need to access some of the protected members of the class from main.cpp. I tried to add, main() as friend, didn't work out and learned that it wont work, so I moved everything in the main() to a test () and made the test() as friend. still it shows the error.
Example would be
//--File.hpp
namespace Files {
class File {
public:
File(long word_):word(word_) {}
protected:
long word;
private:
friend int test();
};
}//ns:Files
//--List_File.hpp
namespace Files {
class List_File :public File {
public:
List_File() : File(sizeof(int) + sizeof(long)) {}
private:
friend int test();
};
}//ns:Files
//--main.cpp
using namespace Files;
int test() {
File *pd = new List_File();
assert(pd->word == 12); //LINE 34
return 0;
}
int main() {
test();
return 0;
}
//it says error on Line 34: Base::value is protected. Please advice.
g++ -O -Wall -Wno-unused -o a.out File.cpp List_File.cpp Data_File.cpp
Free_List_File.cpp main.cpp
File.hpp: In function ‘int test()’:
File.hpp:30:7: error: ‘long int Files::File::word’ is protected
main.cpp:34:16: error: within this context
make: *** [a.out] Error 1
No, it definitely doesn't have to be in the same file, but it obviously has to "know" what the class is, i.e.: the header that has the class definition should be included in the file where the function is implemented. Your code should be fine, as commented.
after you added some context
Your test function is not in the Files namespace. If you want it to be in the global context, you should treat it as "::test" within the namespace, otherwise the compiler might expect the "Files::test" to be the friend function, and not the "::test" as in your case. Can't find the formal standard reference, but I'm pretty sure that's the case. Note that you're performing a forward declaration here, so there's no default fall-back to the upper level of scope for name resolution.
Maybe you missing inheritance declaration in Derived class?
class Derived : public Base {
I've tested your code (with inheritance declaration included) and it produced no error
littedev is right!!
Updated the code according to the comments by littedev..
//--File.hpp
namespace Files {
class File {
public:
File(long word_):word(word_) {}
protected:
long word;
private:
friend int test();
};
}//ns:Files
//--List_File.hpp
namespace Files {
class List_File :public File {
public:
List_File() : File(sizeof(int) + sizeof(long)) {} \
private:
friend int test();
};
}//ns:Files
//--main.cpp
namespace Files{
int test() {
File *pd = new List_File();
assert(pd->word == 12); //LINE 34
return 0;
}
int main() {
Files::test();
return 0;
}
}
I would guess that you are trying to access a protected variable outside of the scope of the Files class definition. I would recommend a function that returns the variable word when it is called and use that instead of trying to access a protected variable outside of a class definition. I could be wrong in that I am not really sure what is the scope of a protected variable (whether it is limited only to class declarations or whether it can be accessed outside of the class definition) but I am pretty sure that I am right because protected variables are like private variables. They are only accessible within the class scope. Correct me if I am wrong.
EDIT: Oh I am sorry I didn't realize what you were doing. littleadv is right, your function declaration isn't within the files namespace.

Redefine Virtual Functions between header files in C++

I have one header file which uses a virtual function.
This is declared and defined:
#ifndef HeaderH
#define HeaderH
class Base {
<some code>
public:virtual int checkVal(int& val) { return val;}
};
#endif
I have another header file which declares some functions, and inherits from this base header.
Finally, I have the implementation of this header file in another .cpp file:
I want to override the virtual function checkVal in my implementation here, but I keep getting a redefinition error.
int Base::checkVal(int& value)
{
if(value == 0)
value = 10;
return value;
}
Is there something I should include in my header file which will override the Base virtual function?
You have already provided the definition of checkval() inside your base class, so why are you redefining it? You can define it only once.If you want to give the implementation inside the .cpp file, just declare checkval() inside the base class, no need to define it there.
Your implementation of checkval() fails if you call it like the following:
Base b;
//some code
b.checkval(10);//Error because temporaries cannot be bound to non-constant references
Is there something I should include in my header file which will override the Base virtual function?
Create a derived class inside the header file and override checkval() then by declaring the function inside the derived class and defining it inside .cpp file.
You have defined the function as { return val;} in the header file, you can't also define it as
{
if(value == 0)
value = 10;
return value;
}
anywhere else in your program. It can only have one definition. It may be that you meant the second definition to be for a derived class (and not Base), but that's not what you have in your code. The fact that your question doesn't use the word class at all tells me you might be confused about how virtual functions work. Read up on them some, it should be pretty obvious how to define a virtual function in a derived class.
It should look something like Derived::checkVal(int & value). note the use of "Derived" as the class name instead of "Base".
xxx.h
#ifndef HeaderH
#define HeaderH
class Base {
virtual int checkVal(int& val); // no definition
};
#endif
xxx.cpp
#include "xxx.h"
int Base::checkVal(int& value)
{
if (value == 0)
value = 10;
return value;
}
And it works fine. Else the compiler will not know what definition to use. There can be only one!
I don't think you mean overriding. And your implementation is missing a return type - it should be:
int Base::checkVal(int& value)
You have two implementations in your Base class, one in the header file, the other in the .cpp file. Just omit the one in the header file.
The error is exactly what you should get.
Without creating a new class that inherits from Base, you cannot redefine the function.
#ifndef DERIVED_H
#define DERIVED_H
#include "base.h"
class Derived : public Base{
<some code>
public:
virtual int checkVal(int& val)
{
if(value == 0)
value = 10;
return value;
}
};
#endif DERIVED_H
Then use Derived where you were going to use Base.
Please read Friendship and Inheritance.