Forward declaration and classes - c++

I am dealing with a situation where I am trying to define two classes that are dependent on each other. This is a simplified example of what I am trying to do.
class a{
public:
int ia;
int printb(b in){
return in.ib;
}
};
class b{
public:
int ib;
int printb(a in){
return in.ia;
}
};
This gives me undefined class b errors. I have tried
class b;
class a{
public:
int ia;
int printb(b in){
return in.ib;
}
};
class b{
public:
int ib;
int printb(a in){
return in.ia;
}
};
But that does not fixed the problem. Any ideas?

All you have to do is to keep the implementation of the member functions outside the class definition. You can then ensure that both classes are defined before implementing the members:
class b;
class a{
public:
int printb(b in);
int ia;
};
class b{
public:
int ib;
int printb(a in);
};
int a::printb(b in){
return in.ib;
}
int b::printb(a in){
return in.ia;
}

Related

How do I avoid forward declarations?

Let's say I have two classes, A and B:
class B;
class A
{
private:
int an_int;
B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
This solution is most probably what is intended in an exercise about inheritance where you can't use a forward declaration.
Instead of the forward declaration
class B;
you can define an interface like
struct I_whoop
{
virtual void whoop_whoop() = 0;
};
then let class B implement that interface, and just use a pointer to the interface.
Actually You can not if using concrete class.
But You can achieve your goal by using template parameters. Making class B a template parameter of template class A.
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
Like this:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
In C and C++ it has never been necessary for a type T to be
forward declared before the declaration of objects of type T *
(or const variants), because the declaration of a T * per se requires
the compiler only to know the size of a T *, not the size or definition
of a T, and the size of a T * is the same, regardless of T.
Here is a more fleshed-out illustration:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n, class B * pb = nullptr) : an_int(n), something_else(pb) {}
int get_int() const {
return an_int;
}
void set_B(class B * pb) {
something_else = pb;
}
class B * get_B() const {
return something_else;
}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n, class A * pa = nullptr) : an_int(n), something_else(pa) {}
int get_int() const {
return an_int;
}
void set_A(class A * pa) {
something_else = pa;
}
class A * get_A() const {
return something_else;
}
};
#include <iostream>
int main()
{
A a(1);
B b(2);
a.set_B(&b);
b.set_A(&a);
std::cout << a.get_B()->get_int() << std::endl;
std::cout << b.get_A()->get_int() << std::endl;
return 0;
}
Output:
2
1
(gcc 4.9.2/clang 3.5.2 -std=c++11 -Wall -pedantic)

Circular reference of two class objects in C++

Is it possible to achieve this code?
class apple;
class fruit{
public: int i;
void set(apple a){
}
};
class apple{
public: int j;
void set(fruit f){
}
};
I know this leads to error: 'a' has incomplete type. even I interchange classes, It always leads to incomplete type error. I have a question can this be achieved? Iam not sure. any help is greatly apprciated. Thanks
Update
class apple;
class fruit{
public: int i;
void set(apple* a);
};
class apple{
public: int j;
void set(fruit f){
}
};
void fruit::set(apple *a){
apple b = *a;
}
I Guess this workaround works. but is there any other solution?
It's possible, but you need to have method definitions outside of the class:
class apple;
class fruit {
public:
int i;
void set(apple a);
};
class apple {
public:
int j;
void set(fruit f);
};
void fruit::set(apple a)
{
i = a.j;
}
void apple::set(fruit f)
{
j = f.i;
}
Using pointers or references, since only the name needs to be known in that case:
class apple;
class fruit{
public:
int i;
void set(apple* a); // OK
void set(apple& a); // Also OK
};
And you need to move the implementation of the function to a place where the definition of apple is known.
You cannot have a circular reference like this. Only possibility is to have a pointer to object used instead of object, as in:
class apple;
class fruit{
public: int i;
void set(apple * a){
}
};
class apple{
public: int j;
void set(fruit * f){
}
};
and manage with de-referenced object within the functions, i.e. use *f within the implementation of these functions apple::set and fruit::set
If you would like to have the object non-modifiable when you pass as a pointer, use as:
class apple;
class fruit{
public: int i;
void set(const apple * a){
}
};
class apple{
public: int j;
void set(const fruit * f){
}
};

How to make these c++ class declarations work

I'm currently reading C++ Primer and am at the point of class friends and member function friends and I'm having trouble figuring out how to get the code that has the following pseudoform to work:
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args); // Compile error: Incomplete Type
};
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
If you try to compile in this form it gives the incomplete type error on the friend line. So the solution is to move the class B definition above class A:
class A;
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) }; // Compile error: Incomplete Type
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args);
};
However now on the vector line, it doesn't know how to create an object of type A, since A has yet to be defined. So then A needs to be defined before B. But now we've arrived back at the original problem. I think this is called circular dependency? I don't know how to fix this with forward declarations.
Any help would be appreciated. Thanks.
I think you will either have to make the whole of class B a friend (which removes a dependency in A anyway so it's probably a good thing), or use a constructor instead of the in-class initializer.
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend class B;
};
class B {
public:
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
Or this
class A;
class B {
public:
B();
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector;
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction();
};
B::B(): someVector{A(5)} { }

How to overwrite a virtual method defined in a class in another class which is inside a function in C++

I have a class A which is in a separate file(sayfile1.cpp)
class A{
public:
virtual int add(){
int a=5;
int b=4;
int c = a+b;
return c;
}
};
Now in a different file(say file2.cpp), i have a function(i have a many other things in this function) inside which i want to create a class inherited from class A and implement the virtual method declared in class A.
void function(Mat param1, Mat param2)
{
//Some process here..
..
..
int c=100;
class B:public A{
public:
virtual int add(){
return c;
}
};
}
Now if i were to call the function int add(), i want the result of c to be 100 and not 9.
Is it possible to do something like this in C++ ??
Thanks in advance
Define member variable:
class B: public A {
int c_;
public:
explicit B(int c):c_(c){};
virtual int add() {
return c_;
}
}
B variable((100));
You need to split your file1.cpp into file1.h:
#ifndef FILE1_H
class A {
public:
virtual int add();
};
#endif
and file1.cpp with it's implementation:
int A::add { /*your code * }
In the other file you include only the header file:
#include "file1.h"
The following is not legal in C++:
void function(Mat param1, Mat param2)
{
//Some process here..
..
..
int c=100;
class B:public A {
public:
virtual int add(){
return c;
}
};
}
Instead, you need something like this:
class B : public A {
public:
B(int v) : c(v) {}
virtual int add(){ return c; }
private:
int c;
};
void function(Mat param1, Mat param2)
{
//Some process here..
..
..
int c=100;
B o(c);
}

make an inner class a friend in C++

I want to make an inner class a friend of an unrelated class but this doesn't seem to work (at least in gcc 4.1.2):
class A {
int i;
friend class B; // fine
friend class B::C; // not allowed?
};
class B {
int geti(A* ap) { return ap->i; }
class C {
int geti(A* ap) { return ap->i; }
};
};
You have to declare B::C before using it. The following might work.
Update: Ignoring a usable demonstration as requested, here's a way of structuring this (minus the definitions of member functions) that could work, but bear in mind that everything is private as it stands.
class A;
class B
{
int geti(A * ap);
public:
class C
{
int geti(A * ap);
};
};
class A
{
friend class B; // fine
friend class B::C; // fine too
int i;
};
Then define the getter functions elsewhere:
int B::geti(A * ap) { ... }
int B::C::geti(A * ap) { ... }
Alternative: forward-declare the nested class B::C and save one external definition:
class A;
class B
{
int geti(const A * ap) const; // we cannot use A yet!
public:
class C;
};
class A
{
friend class B; // fine
friend class B::C; // fine too
int i;
};
int B::geti(const A * ap) const { return ap->i; }
class B::C
{
inline int geti(const A * ap) const { return ap->i; }
};