I don't know what I'm doing wrong.

This is the start of my QStack.cpp file. More funcitons follow, but the post would get too long.

#include "stdafx.h"
#include "QStack.h"
#include <iostream>
using namespace std;

struct Tstruct {
    int value;
    Tstruct * next;
};

struct TStack {
    int value;
    TStack *next;
};

void StackInit(TStack* *TOP) {
    *TOP = NULL;
};

TStack* Push(TStack *a_top, int a_value) {
    TStack *l_hlp;
    l_hlp = new TStack;
    l_hlp->next = a_top;
    l_hlp->value = a_value;
    return l_hlp;
};

int Pop(TStack* *a_top) {
    TStack *l_hlp;
    int l_val;
    l_hlp = *a_top;     
    *a_top = l_hlp->next;
    l_val = l_hlp->value;
    delete l_hlp;           
    return l_val;
};

Next I have a header file QStack.h. I have no idea how it should look, I get some syntax errors either way...

// QStack.h - Contains declarations of some functions
#pragma once


#ifdef QSTACK_EXPORTS
#define QSTACK_API __declspec(dllexport)
#else
#define QSTACK_API __declspec(dllimport)
#endif
class DLLDIR QStack
{
public:
    TStack* Push(TStack *, int);
    void StackInit(TStack* *);
    int Pop(TStack* *);
    void queueInit(Tstruct * *, Tstruct * *);
    void enqueue(Tstruct * *, Tstruct * *, int);
    int Dequeue(Tstruct* *, Tstruct* *);
};

Can anyone hint me a way to declare functions in header files? Also, where do I declare structure types? After I do so, I should build the QStack.cpp to get a DLL file according to some tutorials.

4 Answers

6
Ben. Ayoub On Best Solutions

Here's a simple explanation how the compiler will think while processing your code, The compiler reads from top to bottom.

So if you do something like this:

int var = 0;
StackObject st;

It reads int, what is it? A type! Do I know this type? Yes, builtin in the language.

StackObject? A type I suppose, did I read it somewhere before? No, error!

Then there are 2 things to keep in mind:

  1. Where a declaration suffice
  2. Where a definition suffice

If you use a pointer to a type, a simple declaration is ok.

If you need to use the object, like using it's data/function/invoking constructors, you need a definition.

For instance:

struct declared;
struct defined{};
void f(declared* ptr); // ok
void g(declared copy); // not ok
void w(defined d); // ok
void p(declared* ptr) { ptr->do(); } // not ok

That's why you put it in the header, this way every source file (.cpp) can see how much space the object needs, if it has members, if it has functions and so on.

  • Now let look to your case in more details:

None of the types in your header are declared. What is a TStack? What is a Tstruct? What is DLLDIR?

None of this strictly matters in a header file, because header files aren't compiled. So let's look in your source file. Header files are literally copy/pasted by the pre-processor into your source file at the point of the #include directive. And what do we see? You're still using these types in your class declaration before they've been declared. You have to declare them first! The compiler is not allowed to look later into the source file where they finally are declared.

So the thing to do is to declare all your types that get used in more than one place in header files, and then include those header files where you're using them. So make a header for TStack and then include that header file in your QStack.h. Headers in headers are recursively included when compiling, so the right thing will occur - the TStack will be declared before the QStack uses it.

Another way you can solve this problem is to forward declare your types as such:

struct TStack;

class DLLDIR QStack {
public:
  TStack *Push(TStack *, int);
  // etc...

That way, the compiler knows the type is supposed to exist, and it will defer until linking to worry about the details. Mind you, this has caveats. This is a forward declaration, this isn't a definition. So if you wanted to access any of TStack members, you need the full struct definition in scope which means - header files. TStack needs to be defined before you ever do anything like my_t_stack->value, the compiler isn't going to defer until linking to figure out whether ::value is a member or not and what it's type is.

  • Btw, another thing: using namespace std;

Don't do that, it's a bad habit, it pollutes your namespace and invites slower compilation times and compiler errors. Instead, prefer to bring in symbols in a narrower scope.

0
Pooja Maurya On

Did you check removing this:

#include

in

 #include "stdafx.h"
    #include "QStack.h"
    #include 
    using namespace std;
0
Just Shadow On

I've noticed few mistakes there.
Here is the fixed version of the code (which at least compiles :P).
Added comments the parts which were fixed.

QStack.h file:

#pragma once


#ifdef QSTACK_EXPORTS
#define QSTACK_API __declspec(dllexport)
#else
#define QSTACK_API __declspec(dllimport)
#endif

// MOVED structures here. You might consider moving to another file and include them there as well.
struct Tstruct {
    int value;
    Tstruct * next;
};

struct TStack {
    int value;
    TStack *next;
};

class QStack // < - Removed "DLLDIR" as it was not compiling because of that   
{
public:
    TStack* Push(TStack *, int);
    void StackInit(TStack* *);
    int Pop(TStack* *);
    void queueInit(Tstruct * *, Tstruct * *);
    void enqueue(Tstruct * *, Tstruct * *, int);
    int Dequeue(Tstruct* *, Tstruct* *);
};

QStack.cpp file:

#include "QStack.h"

// Added class name "QStack::" before function name to indicate that that's a member of the class 
void QStack::StackInit(TStack* *TOP) {
    *TOP = nullptr;
};

TStack* QStack::Push(TStack *a_top, int a_value) {
    TStack *l_hlp;
    l_hlp = new TStack;
    l_hlp->next = a_top;
    l_hlp->value = a_value;
    return l_hlp;
};

int QStack::Pop(TStack* *a_top) {
    TStack *l_hlp;
    int l_val;
    l_hlp = *a_top;     
    *a_top = l_hlp->next;
    l_val = l_hlp->value;
    delete l_hlp;           
    return l_val;
};

And here is the code snippet just in case you need: https://onlinegdb.com/r1zVLxMcE

0
Trishant Pahwa On

In QStack.cpp file

#include "stdafx.h"
#include "QStack.h"
#include <iostream>
using namespace std;
struct Tstruct {
    int value;
    Tstruct * next; 
};
struct TStack {
    int value;
    TStack *next;
};
void StackInit(TStack *TOP) {
    *TOP = NULL;
};
TStack* Push(TStack *a_top, int a_value) {
    TStack *l_hlp;
    l_hlp = new TStack;
    l_hlp->next = a_top;
    l_hlp->value = a_value;
    return l_hlp;
};
int Pop(TStack *a_top) {
    TStack *l_hlp;
    int l_val;
    l_hlp = *a_top;
    *a_top = l_hlp->next;
    l_val = l_hlp->value;
    delete l_hlp;
    return l_val;
};

And in QStack.h

// QStack.h - Contains declarations of some functions
#pragma once
#ifdef QSTACK_EXPORTS
#define QSTACK_API __declspec(dllexport)
#else
#define QSTACK_API __declspec(dllimport)
#endif
class DLLDIR QStack {
    public:
        TStack* Push(TStack *next, int value);
        void StackInit(TStack *TOP);
        int Pop(TStack *a_top);
        void queueInit(Tstruct *FRONT, Tstruct *REAR);
        void enqueue(Tstruct *FRONT, Tstruct *REAR, int value);
        int Dequeue(Tstruct *FRONT, Tstruct *REAR);
};

This might work. The errors that I found out were: - This syntax to assign an argument is wrong void StackInit(TStack * *);. Instead, you assign it in this syntax void StackInit(TStack *TOP);, or if you have to assign an argument contains a pointer to a pointer it should follow this syntax void StackInit(TStack **TOP);

  1. Yes, you can declare functions in header files.
  2. You can declare data structure types within the header file as well or in the QStack.cpp file too.
  3. After this you can try building QStack.cpp file to get the DLL file.

Feel free to edit the above code. Let me know if any error arrises in the program.