//
//      DiffusionTerm.h   define the equation class to be solved.
//

#ifndef DIFFUSIONTERM_H
#define DIFFUSIONTERM_H
#include<vector>
#include<iostream>
using namespace std;

class Equation;

class DiffusionTerm
{
private:
 Equation*  pEquation;
public:

	DiffusionTerm(Equation*  _pEquation ){pEquation=_pEquation; };
	~DiffusionTerm(){};

	vector<double>Coe;
	vector<double>source;
    void evaluateCoeAndSource( )
	{
	vector<double>& ThermalConductivity= pEquation->pMedia->getThermalConductivity()  ;

	}
};

//
//      Equation.h   define the equation class to be solved.
//

#ifndef EQUATION_H
#define EQUATION_H

#include "Mesh.h"
#include"Variable.h"
#include"Media.h"
#include"Simulation.h"

#include <string>
#include<vector>
#include <assert.h>
#include <iostream>
#include<map>
using namespace std;

class  DiffusionTerm;

class Equation
{
protected:
// the equation name it should be the same with the variaible name
	string name;
  
	// the equation residual
	double residual;

	// a pointer to the Mesh
   Mesh* pMesh;

	// a pointer to the varible soved in the equation
   Variable* pVariable;
    
  // a pointer to the simulation 
   Simulation* pSimulation;

   DiffusionTerm* pDiffusionTerm;

   // a pointer to the media
   Media* pMedia;
	
   // the matrix A that contain the discretised equation Ax=source
	vector<double> csrA;

	// the source contain the discretised equation source term
	vector<double> source;
	
	map<string,vector<double>> boundaryNameAndVectorMap;

public:
	// the default constructor with no parameter
	Equation() 
	{
		pVariable=new Variable();	
               pDiffusionTerm=new DiffusionTerm(this);
		int size=pMesh->getNbCells(); 
		pVariable->setSize(size); 
		source.resize(size); 
		csrA.resize(pMesh->getNbNoneZero() );
	}
	 // the constructor with one parameter name 
	 Equation(const string& aName) { name=aName; pVariable=new Variable();int size=pMesh->getNbCells(); pVariable->setSize(size);source.resize(size); csrA.resize(pMesh->getNbNoneZero() );}

   ~Equation(){pVariable->clear();delete pVariable;}
};
#endif
#endif

vs2008 gives me the following error:

1>------ Build started: Project: FlowingHeat, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>g:\computation\c++cfd\flowingheat\flowingheat\equation.h(56) : error C2514: 'DiffusionTerm' : class has no constructors
1>        g:\computation\c++cfd\flowingheat\flowingheat\equation.h(19) : see declaration of 'DiffusionTerm'

The problem came from the constructor of Equation. if i delete " pDiffusionTerm=new DiffusionTerm(this);" , it can be compiled sucessfully. Could you please suggest a better way to avoid this circular referencing problem. One way is to declare the class diffusion term in the class equation, but i have many other terms to be defined.
I am confused.
Regards

Recommended Answers

All 5 Replies

A forward-declaration simply announces that a class with that name will be declared later. But to be able to use any of the members of the class (including constructor/destructor or any data members or member functions), the compiler has to have seen the declaration of the class, not just its forward-declaration. So, to allow this circular dependency to work, you have to interleave the declarations and the implementations. You can do this by separating the implementation and declaration, and inserting the inclusion of the required header in between them. This is usually accomplished as so:

In A.h:

#ifndef A_H
#define A_H

class B; //forward-declare class B.

class A {
  public:
    void foo();
    void bar(B* ptr); //declare-only the member function.
};

#endif

In B.h:

#ifndef B_H
#define B_H

class A; //forward-declare class A.

class B {
  public:
    void foo(A* ptr);
};

#endif

In A.cpp:

#include "A.h"   //include the header for the A class.
#include "B.h"   //include the header for the B class's definition.

void A::foo() {
  //..
};

void A::bar(B* ptr) {
  ptr->foo(this);  //now, the compiler has seen the declaration of B, so its member function can be used.
};

In B.cpp:

#include "B.h"
#include "A.h"

void B::foo(A* ptr) {
  ptr->foo();
};

The above will work. If you try to put the definition (or implementation) of the member functions in the header file (within the declaration) the compiler has no way to know what members the forward-declared class has, so how could it compile? Any member function that actually uses the members of the forward-declared class have to appear after the full declaration has been seen, and the above is the way to do it.

Generally, of course, you should not need to use a forward-declaration. You should try to use base classes instead (or templates). If you have "many other terms to be defined", it seems most logical that you would have a base class for _any_ type of term that your equation might use.

A forward-declaration simply announces that a class with that name will be declared later. But to be able to use any of the members of the class (including constructor/destructor or any data members or member functions), the compiler has to have seen the declaration of the class, not just its forward-declaration. So, to allow this circular dependency to work, you have to interleave the declarations and the implementations. You can do this by separating the implementation and declaration, and inserting the inclusion of the required header in between them. This is usually accomplished as so:

In A.h:

#ifndef A_H
#define A_H

class B; //forward-declare class B.

class A {
  public:
    void foo();
    void bar(B* ptr); //declare-only the member function.
};

#endif

In B.h:

#ifndef B_H
#define B_H

class A; //forward-declare class A.

class B {
  public:
    void foo(A* ptr);
};

#endif

In A.cpp:

#include "A.h"   //include the header for the A class.
#include "B.h"   //include the header for the B class's definition.

void A::foo() {
  //..
};

void A::bar(B* ptr) {
  ptr->foo(this);  //now, the compiler has seen the declaration of B, so its member function can be used.
};

In B.cpp:

#include "B.h"
#include "A.h"

void B::foo(A* ptr) {
  ptr->foo();
};

The above will work. If you try to put the definition (or implementation) of the member functions in the header file (within the declaration) the compiler has no way to know what members the forward-declared class has, so how could it compile? Any member function that actually uses the members of the forward-declared class have to appear after the full declaration has been seen, and the above is the way to do it.

Generally, of course, you should not need to use a forward-declaration. You should try to use base classes instead (or templates). If you have "many other terms to be defined", it seems most logical that you would have a base class for _any_ type of term that your equation might use.

Thank you very much for your help. I have little experience about the templates.
In my code, the diffusion need the members from class equation to compute its members.
and equation need the class diffusion to compute its members. so i use a forward-declaration.
could you please give me further detai about the "base class". Do you mean to declare the class diffusion as a derived class of equation.
class diffusionTerm :public class Equation
{}
then the class Diffusion Term can use all the members of Euqation. But, class Euqation can not use class diffusion.

>>then the class Diffusion Term can use all the members of Euqation. But, class Euqation can not use class diffusion.

NO. I mean that you should figure out what the Equation class needs the "DiffusionTerm" class for and create a base class which has those functions that Equation needs as a pure virtual functions, then you derive your DiffusionTerm class from that base class.

To continue on the example I had previously (with classes A and B), you could do this instead of using the circular dependency:

In C.h:

#ifndef C_H
#define C_H

class C {
  public:
    virtual void foo() = 0; //make the function that B needs as a pure virtual function in base class C. 
    virtual ~C() { };
};

#endif

In A.h:

#ifndef A_H
#define A_H

#include "C.h"

//class B; //no need to forward-declare class B. Instead, include B.h:
#include "B.h"

class A : public C {
  public:
    void foo() { //override foo() function.
      //..
    };  
    void bar(B* ptr) {
      ptr->foo(this);
    };
};

#endif

In B.h:

#ifndef B_H
#define B_H

//class A; //no need to forward-declare class A. Instead, use base class C.
#include "C.h"

class B {
  public:
    void foo(C* ptr) {
      ptr->foo();
    };
};

#endif

See how the circular dependency can be replaced by a common dependency on a base class (A depends on C because it inherits from it and implements its interface, and B depends on C to provide the interface it needs).

Attachment show the equation struture need to be solved. It can be sepearted into four parts. unsteady term, the convection term, the diffusionterm and the source term.
So i design the class structures as follows:

class diffusionterm
{
Equation* pEquation;
};
class convectionterm
{
Equation* pEquation;
};
class unseadyterm
{
Equation* pEquation;
};

class source term
{
Equation* pEquation;
};

class Equation
{
diffusionterm* pDiffusionterm;
convectionterm* ;
sourtermterm* ;
unsteayterm* ;

}
could you please suggest me some better structures to avoid the forward declaration problem

>>then the class Diffusion Term can use all the members of Euqation. But, class Euqation can not use class diffusion.

NO. I mean that you should figure out what the Equation class needs the "DiffusionTerm" class for and create a base class which has those functions that Equation needs as a pure virtual functions, then you derive your DiffusionTerm class from that base class.

To continue on the example I had previously (with classes A and B), you could do this instead of using the circular dependency:

In C.h:

#ifndef C_H
#define C_H

class C {
  public:
    virtual void foo() = 0; //make the function that B needs as a pure virtual function in base class C. 
    virtual ~C() { };
};

#endif

In A.h:

#ifndef A_H
#define A_H

#include "C.h"

//class B; //no need to forward-declare class B. Instead, include B.h:
#include "B.h"

class A : public C {
  public:
    void foo() { //override foo() function.
      //..
    };  
    void bar(B* ptr) {
      ptr->foo(this);
    };
};

#endif

In B.h:

#ifndef B_H
#define B_H

//class A; //no need to forward-declare class A. Instead, use base class C.
#include "C.h"

class B {
  public:
    void foo(C* ptr) {
      ptr->foo();
    };
};

#endif

See how the circular dependency can be replaced by a common dependency on a base class (A depends on C because it inherits from it and implements its interface, and B depends on C to provide the interface it needs).

Thank you very much for your help! I get it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.