Solved

C/C++ multiple header file declaration problem

Posted on 2011-02-19
13
1,282 Views
Last Modified: 2012-05-11
I am using Borland C++ Builder to write an application that uses two Units (translation units) saved as Unit1.cpp and Unit2.cpp with corresponding header files Unit1.h an Unit2.h
Unit1 contains the code for class c1 and Unit2 contains the code for class c2.
The problem I have is that I need to call a public function c2->f1(c1 *) taking a parameter of type
pointer to c1 class; furthermore, the body of c2->f1(c1 *) makes reference to a public member of c1

I have a compilation error due to not being able to #include the header files in each unit such that the c1 and c2 types are defined in time.

How do I get round this wihout multiple declarations ( declaring classes in more than one header ) ?

0
Comment
Question by:alcindor
  • 7
  • 6
13 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 34934105
You can do that using foward declarations, e.g.
// Unit1.h

class c2; // foward declaration

class c1 {
public:

  void foo(c2* p);
};

// Unit2.h

class c1; // foward declaration

class c2 {
public:

  void foo(c1* p);
};

Open in new window

0
 
LVL 2

Author Comment

by:alcindor
ID: 34934333
Hello jkr,
   I am familiar with forward declarations and your suggestion does not fix the problem;

Unit2 compiles with one error:

'b' is not a member of c1 because the type is not yet defined

Unit 1 compiles with two errors

undefined structure c2
f2 is not a member of c2 because the type is not yet defined

Unit1.h ///////////////////////////////////

class c2;

//-----------------------------------------
class Tc1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
    c2 *c; //pointer to u2 class
public:		// User declarations
    __fastcall Tc1(TComponent* Owner);
    void f1(c2 *p);
};

Unit1.cpp/////////////////////////////////
//----------------------------------------
__fastcall Tc1::Tc1(TComponent* Owner)
    : TForm(Owner)
{
    c = new c2(); // compiler error - undefined structure c2

}
//----------------------------------------
void Tc1::f1(c2 *p)
{
    c->f2(this); // compiler error - f2 is not a member of c2 because the type is not yet defined

    return;
}
//---------------------------------------

Unit2.h //////////////////////////////////
class c1;

class c2
{
    private:

    public:
    c2();
    ~c2();
    void f2(c1 *fm);
};

Unit2.cpp ////////////////////////////////
//----------------------------------------
c2::c2()
{

}
//----------------------------------------
c2::~c2()
{
}
//----------------------------------------
void c2::f2(c1 *fm)
{
    fm->b = 1;  // compiler error - 'b' is not a member of c1 because the type is not yet defined

}
//----------------------------------------

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
ID: 34934367
Well, in the .cpp file, you do need the actual declaration -- and there you can include both files, preferrably protected with header guards (http://en.wikipedia.org/wiki/Include_guard), e.g.
// Unit1.h
#ifndef UNIT1_H
#define UNIT1_H
class c2; // foward declaration

class c1 {
public:

  void foo(c2* p);
};
#endif

// Unit2.h
#ifndef UNIT2_H
#define UNIT2_H
class c1; // foward declaration

class c2 {
public:

  void foo(c1* p);
};
#endif

// Unit1.cpp
#include "Unit1.h"
#include "Unit2.h"

// ...

Open in new window

0
 
LVL 2

Author Comment

by:alcindor
ID: 34934416
I have added the include guard (Sentinels) and included both header files in each unit and the same errors persist. I have also tried changing the order in which the header files are declared, still the same errors ?
0
 
LVL 86

Expert Comment

by:jkr
ID: 34934507
You are including both header files in Unit1.cpp, are you? (Just to be sure)
0
 
LVL 2

Author Comment

by:alcindor
ID: 34934643
Yes, please find attached the complete code.
Unit2 now compiles without error due to a prior typeing error.
The same compiler errors persist for unit 1 however.

Unit1.h ////////////////////////////////////////
//----------------------------------------------
#ifndef Unit1H
#define Unit1H
//----------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>

class c2;

//----------------------------------------------
class Tc1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
    c2 *c; //pointer to c2 class
public:		// User declarations
    __fastcall Tc1(TComponent* Owner);
    void f1(c2 *p);
};
//----------------------------------------------
extern PACKAGE Tc1 *c1;
//----------------------------------------------
#endif

Unit1.cpp ///////////////////////////////////////
//-----------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"

//-----------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
Tc1 *c1;
//-----------------------------------------------
__fastcall Tc1::Tc1(TComponent* Owner)
    : TForm(Owner)
{
    c = new c2();
}
//-----------------------------------------------
void Tc1::f1(c2 *p)
{
    c->f2(this);
    return;
}
//-----------------------------------------------

Unit2.h /////////////////////////////////////////
//-----------------------------------------------
#ifndef Unit2H
#define Unit2H

//class Tc1;

typedef class c2
{
    private:

    public:
    c2();
    ~c2();
    void f2(Tc1 *fm);
}c2;
//-----------------------------------------------
#endif

Unit2.cpp ///////////////////////////////////////
//-----------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"

//------------------------------------------------
c2::c2()
{

}
//------------------------------------------------
c2::~c2()
{
}
//------------------------------------------------
void c2::f2(Tc1 *fm)
{
    fm->b = 1;  // set caller's data (as an example)
}
//------------------------------------------------

Open in new window

0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 86

Expert Comment

by:jkr
ID: 34934692
Sorry, confusoin on my side - are the actual class names 'c1' and 'c2' or 'Tc1' and 'Tc2'?
0
 
LVL 2

Author Comment

by:alcindor
ID: 34934704
The classes are Tc1 in Unit1 and c2 in Unit2. (I know it's not consistent)
0
 
LVL 86

Expert Comment

by:jkr
ID: 34934788
Hm, I see that you commented out the foward declaration in Unit2.h - does it work if you remove the comment slashes?
0
 
LVL 2

Author Comment

by:alcindor
ID: 34934842
If I don't  comment out the forward declaration in unit 2 then I get a compiler error - Multiple declaration for Tc1
0
 
LVL 86

Expert Comment

by:jkr
ID: 34934986
Weird - if I comment out

fm->b = 1;  // set caller's data (as an example)

it compiles, otherwise not, since Tc1 has no member 'b'...
0
 
LVL 2

Author Comment

by:alcindor
ID: 34935015
Unit 2 compiles ok for me, without the foward declaration but including both header files in the unit2.cpp module in the following order

#include "Unit1.h"
#include "Unit2.h"

I am using Borland C++ Builder 5 Enterprise edition


0
 
LVL 2

Author Comment

by:alcindor
ID: 34938419
I started again from scratch, this time all is ok ?
I don't need the forward declaration in ubit1.h as I am declaring unit2.h before unit1.h in unit1.cpp

Thanks for your comments,

Roger
// UNIT1.h /////////////////////////
//--------------------------------------
#ifndef Unit1H
#define Unit1H
//--------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>

//--------------------------------------
class Tc1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
    c2 *c;
public:		// User declarations
    int b;
    __fastcall Tc1(TComponent* Owner);
    __fastcall ~Tc1();
};
//--------------------------------------
extern PACKAGE Tc1 *c1;
//--------------------------------------
#endif

// UNIT1.cpp ////////////////////
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
//--------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
Tc1 *c1;
//--------------------------------------
__fastcall Tc1::Tc1(TComponent* Owner)
    : TForm(Owner)
{
    c = new c2();
    c->f2(this);// test the function
}
//--------------------------------------
__fastcall Tc1::~Tc1()
{
    delete c;
}
//--------------------------------------

// UNIT2.h /////////////////////////
#ifndef Unit2H
#define Unit2H

class Tc1;

class c2
{
  private:

  public:
  c2();
  void f2(Tc1 *fm);
};

//--------------------------------------
#endif

// UNIT2.cpp //////////////////////
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"

//--------------------------------------
c2::c2()
{

}
//--------------------------------------
void c2::f2(Tc1 *fm)
{
    fm->b = 1;
}
//--------------------------------------
#pragma package(smart_init)

Open in new window

0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now