How to use a class as a type of a function external to the class?

2

How to use a type of a class inside a function external to the class?

For example let's use this example of mathematics. I want to create a class abtracts Bola with two attributes and a function contiene that tells me if a point PuntoRn is in a ball:

class Bola{ 

    private:
        int dim;
        double* adr;

    public: 
        bool contiene(PuntoRn p);
        virtual void Message() = 0;
}; 

class PuntoRn{

    public:
        PuntoRn(int dim, double* adr);
        PuntoRn(const PointRn &);
            // Comment fait on un destructeur ?
        ~PuntoRn(){
            cout << "Destructor de PuntoRn.\n";
        }


    private:
        int dim;
        double* adr;

};

int main(){
    PointRn pa = PointRn(2,0);

    pa = {0,0};

}

However, the terminal tells me

error: ‘PointRn’ has not been declared
   bool contient(PointRn p);
    
asked by ThePassenger 19.02.2017 в 11:38
source

2 answers

4
  

The terminal tells me

error: ‘PointRn’ has not been declared
   bool contient(PointRn p);

And that is the problem; the type PointRn has not been declared.

Declaration.

In C ++ (and several other languages) until a type is declared, the type does not exist. How do you declare a type?:

  

[class / struct / union / enum ] nombre ;

As soon as a type keyword appears, such as class followed by the name of the type, for example PointRn , we consider that the type is declared: we are telling the compiler:

  • There is a type called PointRn that you might use later .

That of later is very important, the statements are read from ↑ up to ↓ below. So if we want to use a type, we must have declared it in previous lines . Therefore, in your code:

/* 01 */ class Bola{ 
/* 02 */ 
/* 03 */     private:
/* 04 */         int dim;
/* 05 */         double* adr;
/* 06 */ 
/* 07 */     public: 
/* 08 */         bool contiene(PuntoRn p);
/* 09 */         virtual void Message() = 0;
/* 10 */ };

In line 8 you are using a type called PuntoRn that has not been declared in any previous line, to solve it you have two solutions:

First option: Change the declaration order.

class PuntoRn{
    public:
        PuntoRn(int dim, double* adr);
        PuntoRn(const PuntoRn &);
        // Comment fait on un destructeur ?
        ~PuntoRn(){
            std::cout << "Destructor de PuntoRn.\n";
        }

    private:
        int dim;
        double* adr;
};

class Bola{ 
    private:
        int dim;
        double* adr;

    public: 
        bool contiene(PuntoRn p);
        virtual void Message() = 0;
};

You can see that we now tell the compiler that PuntoRn exists before it is used as a parameter in Bola::contiene(PuntoRn) .

Second option: Pre-declaration.

C ++ allows to separate the declaration of a type from the type definition. The statement we have already seen how it is done:

// class nombre;
class PuntoRn;

With that we warn the compiler that there is a type with the name PuntoRn , but we do not say anything else: we have not indicated how it is composed, we have not written any member function nor member variables ... in summary: no we have defined it. But despite not being defined, being declared can be used in some contexts:

/* 01 */ class PuntoRn; // Declaración de PuntoRn
/* 02 */ 
/* 03 */ class Bola{ 
/* 04 */ 
/* 05 */     private:
/* 06 */         int dim;
/* 07 */         double* adr;
/* 08 */
/* 09 */     public: 
/* 10 */         bool contiene(PuntoRn p); // Uso de PuntoRn
/* 11 */         virtual void Message() = 0;
/* 12 */ };
/* 13 */
/* 14 */ class PuntoRn{  // Definición de PuntoRn
/* -- */ ...
/* 22 */ };

Declare a type and use it without defining it, it is known in C ++ as Pre-declaration (forward declaration in English). The Pre-declaration allows you to use the type without having defined it, as long as the type is not instanced.

    
answered by 20.02.2017 / 09:22
source
0
class Bola{ 

    private:
        int dim;
        double* adr;

    public: 
        bool contiene(PuntoRn p);
        virtual void Message() = 0;
}; 

The compiler will take that class and will process it to generate binary code. For this code to be valid, the compiler needs to have sufficient information about the types that are used. What is PuntoRn ? Its an object? An alias perhaps? A pointer to function? Since the declaration of PuntoRn is subsequent to the declaration of the function contiene() the compiler can not solve the problem and gives you a compilation error.

To solve the problem you can use the declaration forward or advanced statements:

class PuntoRn; // declaration forward

class Bola{ 

    private:
        int dim;
        double* adr;

    public: 
        bool contiene(PuntoRn p);
        virtual void Message() = 0;
};

Now the compiler is not going to complain because you already know that PuntoRn is a class and that is all you need to know at the moment.

In the implementation of the function the thing changes. At this point, and since you are using PuntoRn by value, the compiler will need to know the PuntoRn interface in order to correctly resolve the dependencies. You can solve this with a #include :

Bola.cpp

#include "PuntoRn.h" // o donde se encuentre la declaración

bool Bola::contiene(PuntoRn p)
{
  // ...
}

You can also, as commented by @Trauma, change the order of the statements but that operation will not work when you have a mutual dependence:

class A
{
  void func1(B);
};

class B
{
  void func2(A);
};

What do you put first? In either case you will have a compilation error, while with declaration forward the solution is trivial.

class B;

class A
{
  void func1(B);
};

class B
{
  void func2(A);
};
    
answered by 20.02.2017 в 10:42