I have a member function in class B and class D that calls the function 'computeValue' which is not a member function of any class. The 'computeValue' function performs some type of algorithm and returns a value. However it seems like I'm getting a lot of compilation errors and not sure what the underlying reasons are. Is it even possible for member functions of classes to call non-member functions?
#include<iostream>
using namespace std;
int computeValue(vector<A*>ex) //Error - Use of undeclared identifier 'A'
{
//implementation of algorithm
}
class A
{
};
class B
{
int sam2()
{
return computeValue(exampleB); // Error - No matching function for call to 'computeValue
}
vector <A*> exampleB;
};
class D
{
int sam1 ()
{
return computeValue(exampleD);// Error - No matching function for call to 'computeValue
}
vector<A*> exampleD;
};
int main()
{
}
computeValue needs the declaration of class A, so declare A before it:
class A
{
};
int computeValue(vector<A*>ex)
{
//implementation of algorithm
}
Is it even possible for member functions of classes to call non-member functions?
Of cource, yes.
Yes, definitely you can call class non-member function from class.
Here you are getting errors because of mainly two issue:
You are using vector but you haven't declared vector header file in your code.
#include<vector>
You are using class A pointer as a parameter to function "computeValue" which is defined before the class A.
So either define class A before function or use forward declaration concept.
Here is error free modified code:
#include<iostream>
#include<vector>
using namespace std;
**class A; //forward declaration of Class A**
int computeValue(vector<A*> ex) //Error - Use of undeclared identifier 'A'
{
//implementation of algorithm i
return 5;
}
class A
{
};
class B
{
int sam2()
{
return computeValue(exampleB); // Error - No matching function for call to 'computeValue
}
vector <A*> exampleB;
};
class D
{
public:
D()
{
cout<<"D constructor"<<endl;
}
int sam1 ()
{
return computeValue(exampleD);// Error - No matching function for call to 'computeValue
}
vector<A*> exampleD;
};
int main()
{
D d;
}
This code will give you output: "D constructor"
I hope this will help you.
Related
When i compile the code below i don't get any error and on debugging it initializes the class data member a of class
abc to zero. Can someone just tell me how is the compiler differentiating between the two. I dont see it happening in runtime.
//A function friendly to two classes (finding maximum of objects of 2 classes(one data member in class)
#include <iostream>
#include <conio.h>
using namespace std;
class abc; //Forward Declaration
class xyz
{
int x;
public :
void inivalue(float);
friend float max(xyz,abc);
};
class abc
{
int a;
public :
void inivalue(float);
friend float max(xyz,abc);
};
void xyz::inivalue(float y)
{
x=y;
}
void abc::inivalue(float a)
{
a=a;
}
float max(xyz m,abc n)
{
if(m.x > n.a)
return m.x;
else
return n.a;
}
int main()
{
system("cls");
xyz o1;
abc o2;
o1.inivalue(10);
o2.inivalue(20);
cout<<"The maximum of 2 classes is : "<<max(o1,o2)<<endl;
}
That's called "variable shadowing".
When you do that, the local variable a "shadows" the class variable. The compiler will use the local variable, so in the inivalue function of the class abc you're just setting the parameter value to itself.
The a member of the class is unitialized when it is used in the max and the code will result in Undefined Behaviour.
Lippman 5th
ISBN-13: 978-0321714114
Page 280-281, it says:
Making A Member Function a Friend
Rather than making the entire Window_mgr class a friend, Screen can
instead specify that only the clear member is allowed access. When we
declare a member function to be a friend, we must specify the class of
which that function is a member:
class Screen {
// Window_mgr::clear must have been declared before class Screen
friend void Window_mgr::clear(ScreenIndex);
// ... rest of the Screen class
};
Making a member function a friend requires careful structuring of our
programs to accommodate interdependencies among the declarations and
definitions. In this example, we must order our program as follows:
First, define the Window_mgr class, which declares, but cannot define, clear. Screen must be declared before clear can use the
members of Screen.
Next, define class Screen, including a friend declaration for clear.
Finally, define clear, which can now refer to the members in Screen.
The problem is: class Window_mgr has a data member that depends of class
Screen definition. See:
class Window_mgr {
public:
// location ID for each screen on the window
using ScreenIndex = std::vector<Screen>::size_type;
// reset the Screen at the given position to all blanks
void clear(ScreenIndex);
private:
std::vector<Screen> screens{Screen(24, 80, ' ')};
};
So it is impossible firstly define Window_mgr without defining Screen
previously!
And at the same time, it is impossible define Screen without we have
defined Window_mgr!!!
How can this problem be solved???
Is the book wrong?
I will paste here a code so that you can repeat the problem using a
minimal code:
#include <iostream>
#include <string>
#include <vector>
class A
{
friend void B::hello();
public:
A(int i) : number{i} {}
private:
void f() {
std::cout << "hello" << std::endl;
}
int number;
};
class B {
private:
std::vector<A> x{A(10)};
public:
void hello()
{
for(A &elem : x)
{
elem.f();
}
}
};
int main()
{
A x;
return 0;
}
If I compile this code, the result is:
error: use of undeclared identifier 'B'
friend void B::hello();
And if I invert the position (A <--> B), I have:
error: use of undeclared identifier 'A'
std::vector x{A(10)};
Is there a correct way to do that??
Thank you!
EDIT:
Thank you, Craig Young
Solution:
#include <iostream>
#include <string>
#include <vector>
class A;
class B {
private:
std::vector<A> x;
public:
B();
void hello();
};
class A
{
friend void B::hello();
public:
A(int i) : number{i} {}
private:
void f() {
std::cout << "hello" << std::endl;
}
int number;
};
B::B() : x{A(10)}
{
}
void B::hello()
{
for(A &elem : x)
{
elem.f();
}
}
int main()
{
return 0;
}
Conclusion:
the book is incomplete in that it doesn't expose the necessity of doing the forward declaration of class A firstly and the impossibility to do in-class initialization in this case.
I didn't notice that the problem was the A(10), not the vector! That is, we can use incomplete type A (only declaration, without definition) when we are using it as Template argument to vector (because it doesn't create A object itself) but we can not use incomplete type A when defining a object, for example: A(10);
For a start
Well, you're not following the guidance correctly.
First, define the Window_mgr class, which declares, but cannot define, clear. Screen must be declared before clear can use the members of Screen.
You must declare B before A.
Next, define class Screen, including a friend declaration for clear.
Now declare A with B::hello() as a friend.
Finally, define clear, which can now refer to the members in Screen.
B:hello() can use the private members of A.
This has been covered before here: C++ Forward declaration , friend function problem
You've added complications
Furthermore you want declarations of B to reference A. To achieve this you need to forward declare A so that B knows of its existence.
And it's important to be aware that you have only "partial" access to A. You cannot 'fully use' A in the declaration of B. So the following line in B is wrong.
//You're trying to create A when you only know it exists.
//You don't have a full definition of A yet.
std::vector<A> x{A(10)};
//Replace the above with...
std::vector<A> x;
Of course you'll have to find another way to initialise x.
Sample code
#include <iostream>
#include <vector>
class A;
class B
{
private:
std::vector<A> x;
public:
void hello();
};
class A
{
friend void B::hello();
public:
A(int i): number(i) {}
private:
void f() { std::cout << "hello" << std::endl; }
int number;
};
void B::hello()
{
for(A &elem : x)
{
elem.f();
}
}
int main()
{
A a{5};
return 0;
}
You have to have an earlier declaration, but not an earlier definition.
Adding
class A;
class B;
at the front tells the compiler that “A” and “B” refer to classes. That should be enough for it to reason out the rest.
I am unable to run the following code. As namesapces are different, why there are still showing errors as mentioned below?
error: conflicting declaration 'NS2::Base B'
NS2::Base B;
#include<iostream>
using namespace std;
namespace NS1
{
class Base
{
int x=4;
public:
void disp()
{
cout<<x<<endl;
}
};
}
namespace NS2
{
class Base
{
int x=7;
public:
void disp()
{
cout<<x<<endl;
}
};
}
int main()
{
NS1::Base B;
NS1:B.disp();
NS2::Base B;
NS2::B.disp();
}
Namespaces contain only what is declared inside them, in your case the two classes Base. The two objects called B however are not declared in any namespace (but are both scoped to the function main), so you get a conflicting declaration error. It doesn't matter that the associated classes where declared in different namespaces.
Just the class Base is part of namespace NS1,
B1 is just an object of type NS1::Base defined in main() not in NS1. Same goes for B2 and NS2.
Thats why you can't call function using scope resolution operator on B1.
Objects are defined in main() so you have too keep names different too
int main()
{
NS1::Base B1;
B1.disp();
NS2::Base B2;
B2.disp();
}
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.
Very new to c++ having trouble calling a function from another class.
Class B inherits from Class A, and I want class A to be able to call a function created in class B.
using namespace std;
class B;
class A
{
public:
void CallFunction ()
{
B b;
b.bFunction();
}
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
It all looks fine on screen (no obvious errors) but when I try to compile it i get an error C2079 'b' uses undefined class B.
I've tried making them pointers/ friends but I'm getting the same error.
void CallFunction ()
{ // <----- At this point the compiler knows
// nothing about the members of B.
B b;
b.bFunction();
}
This happens for the same reason that functions in C cannot call each other without at least one of them being declared as a function prototype.
To fix this issue we need to make sure both classes are declared before they are used. We separate the declaration from the definition. This MSDN article explains in more detail about the declarations and definitions.
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{ ... }
};
void A::CallFunction ()
{
B b;
b.bFunction();
}
What you should do, is put CallFunction into *.cpp file, where you include B.h.
After edit, files will look like:
B.h:
#pragma once //or other specific to compiler...
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
B.cpp
#include "B.h"
void A::CallFunction(){
//use B object here...
}
Referencing to your explanation, that you have tried to change B b; into pointer- it would be okay, if you wouldn't use it in that same place. You can use pointer of undefined class(but declared), because ALL pointers have fixed byte size(4), so compiler doesn't have problems with that. But it knows nothing about the object they are pointing to(simply: knows the size/boundary, not the content).
So as long as you are using the knowledge, that all pointers are same size, you can use them anywhere. But if you want to use the object, they are pointing to, the class of this object must be already defined and known by compiler.
And last clarification: objects may differ in size, unlike pointers. Pointer is a number/index, which indicates the place in RAM, where something is stored(for example index: 0xf6a7b1).
class B is only declared but not defined at the beginning, which is what the compiler complains about. The root cause is that in class A's Call Function, you are referencing instance b of type B, which is incomplete and undefined. You can modify source like this without introducing new file(just for sake of simplicity, not recommended in practice):
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
// postpone definition of CallFunction here
void A::CallFunction ()
{
B b;
b.bFunction();
}
in A you have used a definition of B which is not given until then , that's why the compiler is giving error .
Forward declare class B and swap order of A and B definitions: 1st B and 2nd A. You can not call methods of forward declared B class.
Here's my solution to the issue. Tried to keep it straight and simple.
#include <iostream>
using namespace std;
class Game{
public:
void init(){
cout << "Hi" << endl;
}
}g;
class b : Game{ //class b uses/imports class Game
public:
void h(){
init(); //Use function from class Game
}
}A;
int main()
{
A.h();
return 0;
}
You can also have a look at the curiously recurring template pattern and solve your problem similar to this:
template<typename B_TYPE>
struct A
{
int callFctn()
{
B_TYPE b;
return b.bFctn();
}
};
struct B : A<B>
{
int bFctn()
{
return 5;
}
};
int main()
{
A<B> a;
return a.callFctn();
}