Friend Functions

Cbottle.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once;
class CCarton; // Forward declaration
class CBottle
{
public:
CBottle(double height, double diameter)
{
m_Height = height;
m_Diameter = diameter;
}
double m_Height; // Bottle height
double m_Diameter; // Bottle diameter
// Let the carton constructor in
friend CCarton::CCarton(const CBottle& aBottle);
};



CCarton.h

1
2
3
4
5
6
7
8
9
10
#pragma once
class CBottle; // Forward declaration
class CCarton
{
public:
CCarton(const CBottle& aBottle);
double m_Length; // Carton length
double m_Width; // Carton width
double m_Height; // Carton height
};


CCarton.cpp

1
2
3
4
5
6
7
8
#include "Box.h"
#include "CandyBox.h"
CCarton::CCarton(const CBottle& aBottle)
{
m_Height = aBottle.m_Height; // Bottle height
m_Length = 4.0*aBottle.m_Diameter; // Four rows of ...
m_Width = 3.0*aBottle.m_Diameter; // ...three bottles
}


Shouldn't line 15 in CBottle.h give you a error. Isnt it a incomplete type, because it is only a forward declaration and the compiler doesnt know what CCarton contains?

It does give you that error if you change it to this:

Take out CCarton.cpp

And change CCarton.h to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
class CBottle; // Forward declaration
class CCarton
{
public:
CCarton(const CBottle& aBottle)
{
m_Height = aBottle.m_Height; // Bottle height
m_Length = 4.0*aBottle.m_Diameter; // Four rows of ...
m_Width = 3.0*aBottle.m_Diameter; // ...three bottles
}
private:
double m_Length; // Carton length
double m_Width; // Carton width
double m_Height; // Carton height
};


But why does it give that error now?

Hope someone can explain. For now good night I will see you in the morning :D
Last edited on
Well how can you access any fields of the bottle class if you only forward declare it? One of the headers included in your CCarton.cpp file must be including Cbottle.h. This is then not included in just the header file, so the constructor can't access any of the fields in bottle.
Shouldn't line 15 in CBottle.h give you a error. Isnt it a incomplete type, because it is only a forward declaration and the compiler doesnt know what CCarton contains?

Yes, it's incomplete. No, it shouldn't give you an error, because you're only declaring a method, and declaring reference to the class. Nowhere in CBottle.h are you doing anything that requires the compiler to know the definition of CCarton, so it's OK to use an incomplete type.

This is why it's often a good thing to use references and/or pointers in your class definition headers - it allows you to avoid header file dependencies, which can slow down compilation time a lot when you're working on a project of a significant size.
But why does it give me that error if I add my constructor back in? My constructor gives the error because it needs to access dimensions of the aBottle class which is why, but doesn't the CCarton do the same? Accessing my constructor?
Last edited on
But why does it give me that error if I add my constructor back in?

That should be obvious - in your second version of CCarton.h, the compiler does need to know the definition of CBottle, because you're accessing the members of CBottle.
Last edited on
So you dont exactly access the member in
 
friend CCarton::CCarton(const CBottle& aBottle);


But it gives me a error that it needs to in that line if I use the second version with the cpp file.

Try it out for your self! Atleast it highlights it as red and says Incomplete Type not allowed.
Last edited on
Yes. If you use the second version, then the constructor is accessing members of CBottle, so you need to have CBottle already defined (by including the header file).
friend CCarton::CCarton(const CBottle& aBottle);


That code is in CBottle, and isnt it accessing CCarton, which is not defined, only declared.

I know why the second wont work, but if I use the second, the constructor in CCarton gives me a error as well this line in CBottle.

My question is why this line is also giving a error with that constructor but none if it the constructor is in the cpp?
That code is in CBottle, and isnt it accessing CCarton, which is not defined, only declared.

I don't think so. It's just declaring that there exists a method called CCarton::Carton, that takes a reference to a CBottle.

I know why the second wont work, but if I use the second, the constructor in CCarton gives me a error as well this line in CBottle.

My question is why this line is also giving a error with that constructor but none if it the constructor is in the cpp?

Sorry, I'm genuinely unclear what you're trying to say here. Can you post the versions of the files (header and cpp files) that are giving you the errors? And, as always, give us the errors too?
Last edited on
Alright on it!
Error Versions:

CBottle:

1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once
class CBottle
{
public:
CBottle(double height, double diameter)
{
m_Height = height;
m_Diameter = diameter;
}

double m_Height; // Bottle height
double m_Diameter; // Bottle diameter
};



CCarton:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once;
class CCarton; // Forward declaration
class CBottle
{
public:
CBottle(double height, double diameter)
{
m_Height = height;
m_Diameter = diameter;
}

double m_Height; // Bottle height
double m_Diameter; // Bottle diameter
// Let the carton constructor in
friend CCarton::CCarton(const CBottle& aBottle);
};



Main:

1
2
3
4
5
6
7
8
9
10
11
12
#include "CCarton.h"
#include "CBottle.h"
#include <iostream>

using namespace std;

int main ()
{
	CBottle nib;

	return 0;
}


Output:

1>------ Build started: Project: Tests, Configuration: Debug Win32 ------
1>  Main.cpp
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(9): error C2027: use of undefined type 'CBottle'
1>          c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(2) : see declaration of 'CBottle'
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(9): error C2228: left of '.m_Height' must have class/struct/union
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(10): error C2027: use of undefined type 'CBottle'
1>          c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(2) : see declaration of 'CBottle'
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(10): error C2228: left of '.m_Diameter' must have class/struct/union
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(11): error C2027: use of undefined type 'CBottle'
1>          c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(2) : see declaration of 'CBottle'
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 09\ex9_05\ccarton.h(11): error C2228: left of '.m_Diameter' must have class/struct/union
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Compiling Versions

Main:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "CCarton.h"
#include "CBottle.h"
#include <iostream>

using namespace std;

CCarton::CCarton(const CBottle& aBottle)
{
m_Height = aBottle.m_Height; // Bottle height
m_Length = 4.0*aBottle.m_Diameter; // Four rows of ...
m_Width = 3.0*aBottle.m_Diameter; // ...three bottles
}

int main ()
{ cout<<"No Error"<<endl;
return 0;}


CBottle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once;
class CCarton; // Forward declaration
class CBottle
{
public:
CBottle(double height, double diameter)
{
m_Height = height;
m_Diameter = diameter;
}
double m_Height; // Bottle height
double m_Diameter; // Bottle diameter
// Let the carton constructor in
friend CCarton::CCarton(const CBottle& aBottle);
};


CCarton:

1
2
3
4
5
6
7
8
9
10
11
#pragma once
class CBottle; // Forward declaration
class CCarton
{
public:
CCarton(const CBottle& aBottle);

double m_Length; // Carton length
double m_Width; // Carton width
double m_Height; // Carton height
};



Output:

No Error
Press any key to continue . . .
Last edited on
Look here is what my book says on the ones that do not compile:

"You might think that this will compile correctly, but there is a problem. The CCarton class definition refers to the CBottle class, and the CBottle class with the friend function added refers to the CCarton class, so you have a cyclic dependency here. You can put a forward declaration of the CCarton class in the CBottle class, and vice versa, but this still won’t allow the classes to compile. The problem is with the CCarton class constructor. This appears within the CCarton class definition and the compiler cannot compile this function without having first compiled the CBottle class. On the other hand, it can’t compile the CBottle class without having compiled the CCarton class. The only way to resolve this is to put the CCarton constructor definition in a .cpp file. The header file holding the CCarton class iinition will be:"

See it says that line 15 refers to thing so it has to be compiled but I dont understand why, its only a declaration, so why?

And it should continue to give the error because even after when it still does not have access to the definition...

Based on all this I do not think that line 15 should matter much.

Another way to fix it by simplying adding CCarton.h to CBottle.h.


If you dont understand my question just ask, I really need this answered. Thanks!
Last edited on
Can someone please help!
Topic archived. No new replies allowed.