I've been looking for an answer to this for several hours. Even though I have a workaround I'd like to understand the problem. I get an undefined reference error when linking the following:
.h:
class Test
{
public:
class Class1
{
public:
Class1(int i);
int x;
void Inc();
};
static Class1 one;
static int F1();
};
.cpp:
#include "Test.h"
Test::Class1 one(0);
void Test::Class1::Inc()
{
x++;
}
Test::Class1::Class1(int i)
{
x = i;
}
int Test::F1()
{
//extern Test::Class1 one;
one.Inc();
return one.x;
}
I get an undefined reference to Test:one in the F1 function. If I add the extern Test::Class1 one it seems to work. Why is this necessary?
This is a little confusing due to the nested class, but it's as simple as:
Test::Class1 Test::one(0);
The following statement in your code, just defines a global objet one that happens to be of a nested type: Test::Class1 :
Test::Class1 one(0);
If it wasn't of a nested type, you'd immediately have noticed the missing qualifier ;-)
Related
class Example{
public:
friend void Clone::f(Example);
Example(){
x = 10;
}
private:
int x;
};
class Clone{
public:
void f(Example ex){
std::cout << ex.x;
}
};
When I write f as a normal function, the program compiles successful. However, when I write f as a class member, this error occurs.
Screenshot:
The error you're seeing is not a root-cause compilation error. It is an artifact of a different problem. You're friending to a member function of a class the compiler has no earthly clue even exists yet,much less exists with that specific member.
A friend declaration of a non-member function has the advantage where it also acts as a prototype declaration. Such is not the case for a member function. The compiler must know that (a) the class exists, and (b) the member exists.
Compiling your original code (I use clang++ v3.6), the following errors are actually reported:
main.cpp:6:17: Use of undeclared identifier 'Clone'
main.cpp:17:25: 'x' is a private member of 'Example'
The former is a direct cause of the latter. But doing this instead:
#include <iostream>
#include <string>
class Example;
class Clone
{
public:
void f(Example);
};
class Example
{
public:
friend void Clone::f(Example);
Example()
{
x = 10;
}
private:
int x;
};
void Clone::f(Example ex)
{
std::cout << ex.x;
};
int main()
{
Clone c;
Example e;
c.f(e);
}
Output
10
This does the following:
Forward declares Example
Declares Clone, but does not implement Clone::f (yet)
Declares Example, thereby making x known to the compiler.
Friends Clone::f to Example
Implements Clone::f
At each stage we provide what the compiler needs to continue on.
Best of luck.
How could I make a function only seen by the function that calls it?
define the function I want to hide as private function is not enough, as it could still be seen by other public functions in the class.
Now I use lambda expression to define anonymous function inside function. Is there any better solution?
Aside from using a lambda (which you've rejected), you could implement your function in its own compilation unit, and code the supporting function in an anonymous namespace within that compilation unit.
But that supporting function would be outside the class, so you'd have to pass it all the parameters it needed. That could become unwieldly though no worse than a long lambda capture list.
You can use a function object. For example(you can compile this, even in C++03):
#include <iostream> // only for output
class foo{
int bar(){return 0;} // Only foo can see this
public:
int operator()(){
return bar();
}
};
class baz{
public:
foo do_foo;
};
int main(){
baz a;
std::cout << a.do_foo() << std::endl;
}
the method bar is only visible by a foo.
P.S.: If you need foo to access members of baz, make it a friend.
A simmilar approach to cassiorenan would be to use static class functions and friends.
Something like this:
void Boss();
class Worker {
static void Test(){ return;}
friend void Boss();
};
void Boss(){
Worker::Test();
}
Though why would you want to do this, I don't know.
It is possible to define function inside a function without lambdas. Just define a struct that contains required function. This approach is not much better than using lambda, but at least this is straightforward and works with older compilers too.
int func() {
struct {
int hiddenFunc() {
return 1;
}
} h;
int a = h.hiddenFunc() + h.hiddenFunc();
return a;
}
As a slight variation from cassiorenan's solution, you could use a class containing one public static function (the visible function) and one static private function that could only be called from there. To avoid creation of objects of that class, it is enough to put a private constructor.
EDIT:
Per cassiorenan's comment, I can see that OP really needs methods and not functions. In that case, I would still use a dedicated class in a anonymous namespace to ensure it is not visible from elsewhere (even if my example is single file ...) friend to the class really used. So in below example, bar is the business class that would have a method with an externally hidden implementation (here relay_method), and foo is dedicated to the hidden method called with a pointer to the real object. In real world, the whole anonymous namespace and the implementation of the hidden method should be in the implementation file bar.cpp.
That way, the real implementation function priv_func can only be called from a bar object through bar::relay_method() and foo::bar_func(bar &).
#include <iostream>
class bar;
namespace {
class foo {
private:
static int priv_func(int i) {
return i * i;
}
foo() {}
public:
// only useful if true functions were needed
/* static int pub_func(int i, int j) {
return priv_func(i) + priv_func(j);
}*/
static void bar_func(bar& b);
};
}
class bar {
int x;
int x2;
public:
bar(int i): x(i) {}
void relay_method() {
foo::bar_func(*this);
}
friend class foo;
int getX2() const {
return x2;
}
};
void foo::bar_func(bar& b) {
b.x2 = foo::priv_func(b.x);
}
using namespace std;
int main() {
/* int i = foo::pub_func(3,4);
cout << i << endl;
// foo::priv_func(2); error access to private member of class foo
// foo f; */
bar b(2);
b.relay_method();
cout << b.getX2() << endl;
return 0;
}
I have two classes, Friend2 is a friend of Friend1. After Friend2 accesses the Friend1's private member variable, I want Friend1 to be able to access the Friend2's public member functions. So I decided to use composition inside Friend1. However, the compiler shows me the error:
use of undefined type 'friend2'
Then, I tried another way, making Friend1 a friend of Friend2 too. But I still got the same error. Would anyone teach me the way to solve? Thx a lot!
#ifndef FRIEND1_H
#define FRIEND1_H
class friend2;
class friend1 {
private:
int x;
public:
friend1();
int comp(friend2* f2o);
friend class friend2;
};
friend1::friend1() {
x = 1;
}
int friend1::comp(friend2* f2o) {
return f2o->getxx(); //the error : use of undefined type
}
#endif
#ifndef FRIEND2_H
#define FRIEND2_H
#include "friend1.h"
#include <iostream>
class friend2 {
private:
int xx;
public:
friend2();
void p(friend1* f1o);
int getxx() const;
friend class friend1;
};
friend2::friend2() {}
void friend2::p(friend1* f1o) {
xx = f1o->x;
}
int friend2::getxx() const {
return xx;
}
#endif
Also, is composition or friend class the better way to do this? Why?
You get //the error : use of undefined type because class Friend2 is only declared, not defined at that point. To solve this move int friend1::comp(friend2* f2o) implementation to friend1.cpp and include friend2.h from there.
UPDATE In general, if two classes are mutual friends (and even if only one of them is a friend to another), it's a good reason to think about the design.
I have this class that has a static member. it is also a base class for several other classes in my program. Here's its header file:
#ifndef YARL_OBJECT_HPP
#define YARL_OBJECT_HPP
namespace yarlObject
{
class YarlObject
{
// Member Variables
private:
static int nextID; // keeps track of the next ID number to be used
int ID; // the identifier for a specific object
// Member Functions
public:
YarlObject(): ID(++nextID) {}
virtual ~YarlObject() {}
int getID() const {return ID;}
};
}
#endif
and here's its implementation file.
#include "YarlObject.hpp"
namespace yarlObject
{
int YarlObject::nextID = 0;
}
I'm using g++, and it returns three undefined reference to 'yarlObject::YarlObject::nextID linker errors. If I change the ++nextID phrase in the constructor to just nextID, then I only get one error, and if I change it to 1, then it links correctly. I imagine it's something simple, but what's going on?
Make sure you are linking against the generated .o file. Double-check the makefile.
I'm unfamiliar to working in c++ under linux so I have some issues, one of them is that after I write a class and try to instantiate an object of that class I get to following error : "undefined reference to Constructor_of_that_class" . This happens for every class that I write , and it happens no matter where I try to do the instantiating, even if the code compiles without any problems . What is going wrong here and what I have to do to get over this error ? Because the project that I'm working wasn't created by me I suspect that it has to do something with some settings but I don't know which.
Edit (pasted from comment):
Well if I define a class this:
class test {
public:
int a*;
test( int* a)
}
class test {
test::test( int* a)
{
this->a=a;
}
}
and then in any class of those who where previously defined I use:
test t =new test( anIntPointer);
then I get a undefined reference to test::test(int*);
I would be surprised if your code sample even compiles, so fixing all other compilation errors first would be a good start. Here is a short code sample that might help:
// Class declaration
class test
{
private:
// Member variable - should be private.
int* a;
public:
// Constructor declaration.
test(int* a);
// Inline function definition.
int getA()
{
return *a;
}
};
// Constructor declaration.
test::test( int* a)
{
this->a=a;
}
int main()
{
int i = 7;
test t(&i);
i++;
// Should return 8.
return t.getA();
}
Without code its impossible to tell, but make sure that your class definitions end with a semi-colon;
Do this:
test.h
class Test {
public:
int a*;
Test( int *a );
}; //Missing this semi colon might be your problem
test.cpp
#include "test.h"
Test::Test( int *a )
{
this->a = a;
}
int main()
{
int *anIntPointer;
Test t = new Test( anIntPointer );
return 0;
}
Don't wrap the constructor definition (the test::test() function) inside a class test block. That effectively defines a new class with the same name but it's different from the one in your header. Make it look like this:
// .h file
class test {
public:
int *a;
test( int* a)
};
// .cpp file
test::test( int* a)
{
this->a=a;
}
You should provide some code of one of your class (definition + implementation) if you want a better answer.
With the minimal explaination you provide, I think your constructor have no implementation.
Try this:
foo.h
class test {
public:
int a*;
test( int* a)
};
foo.cpp
test::test( int* a)
{
this->a=a;
}
Semantics aside from the comment I made above (I'm a little low on the whole blood sugar), you state that you're instantiating test thus:
test t =new test( anIntPointer);
the new operator returns a pointer to the object, not the object itself - you should be instantiating it:
test *t = new test(anIntPointer);
(and, going back to semantics, convention for C++ classes is a capitalised first letter, I believe :-) )
Your posted class definition is syntactically invalid. A correct equivalent would be:
class test {
public:
int *a;
test (int *a) : a(a) {}
};
Does this compile?