-2

I wanted to make a class library so that I can use it across my codes. That's why i splitted my class in 2 files - s_int.h and s_int.cpp But the compilation is giving too many errors related to the class. generally i see some 'anonymous aggregate' related to constructors and destructors errors. Here is my code :


main.cpp :

#include "s_int.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
    s_int integer;
    integer = "11111111111111111111111111111111111";
    s_int integer1(integer);
    cout << integer.integer << "\n";
    cout << integer1.integer << "\n";
}

s_int.cpp

#include <bits/stdc++.h>
#include "s_int.h"
using namespace std;
 
    s_int::s_int(std::string inp) 
    {
        this-> integer = inp;
    }
    s_int::s_int(const s_int &inp) 
    {
        this-> integer = inp.integer;
    }
    void s_int::operator = (const string &inp )
    {
        integer = inp;
    }
    void s_int::operator = (const s_int &inp )
    {
        integer = inp.integer;
    }

s_int.h

#include <bits/stdc++.h>
#ifndef s_int
#define s_int
using namespace std;
class s_int
{
    public:
        string integer = "";
        s_int(std::string inp = "") ;
        s_int(const s_int &inp) ;
        void operator = (const string &inp );
        void operator = (const s_int &inp );
};
#endif

compilation errors (in case needed)

$ g++ main.cpp s_int.h s_int.cpp
main.cpp: In function ‘int main()’:
main.cpp:7:11: error: ‘integer’ was not declared in this scope
    7 |     s_int integer;
      |           ^~~~~~~
main.cpp:9:11: error: ‘integer1’ was not declared in this scope
    9 |     s_int integer1(integer);
      |           ^~~~~~~~
s_int.h:9:26: error: expected ‘)’ before ‘inp’
    9 |         s_int(std::string inp = "") ;
      |              ~           ^~~~
      |                          )
s_int.h:10:15: error: expected unqualified-id before ‘const’
   10 |         s_int(const s_int &inp) ;
      |               ^~~~~
s_int.h:10:15: error: expected ‘)’ before ‘const’
   10 |         s_int(const s_int &inp) ;
      |              ~^~~~~
      |               )
s_int.h:13:33: error: ‘inp’ has not been declared
   13 |         s_int operator + (s_int inp );
      |                                 ^~~
s_int.h:8:16: error: member ‘std::string <unnamed class>::integer’ with constructor not allowed in anonymous aggregate
    8 |         string integer = "";
      |                ^~~~~~~
s_int.h:8:16: error: member ‘std::string <unnamed class>::integer’ with destructor not allowed in anonymous aggregate
s_int.h:8:16: error: member ‘std::string <unnamed class>::integer’ with copy assignment operator not allowed in anonymous aggregate
s_int.h:14:2: error: abstract declarator ‘<unnamed class>’ used as declaration
   14 | };
      |  ^
In file included from s_int.cpp:2:
s_int.h:9:26: error: expected ‘)’ before ‘inp’
    9 |         s_int(std::string inp = "") ;
      |              ~           ^~~~
      |                          )
s_int.h:10:15: error: expected unqualified-id before ‘const’
   10 |         s_int(const s_int &inp) ;
      |               ^~~~~
s_int.h:10:15: error: expected ‘)’ before ‘const’
   10 |         s_int(const s_int &inp) ;
      |              ~^~~~~
      |               )
s_int.h:13:33: error: ‘inp’ has not been declared
   13 |         s_int operator + (s_int inp );
      |                                 ^~~
s_int.h:8:16: error: member ‘std::string <unnamed class>::integer’ with constructor not allowed in anonymous aggregate
    8 |         string integer = "";
      |                ^~~~~~~
s_int.h:8:16: error: member ‘std::string <unnamed class>::integer’ with destructor not allowed in anonymous aggregate
s_int.h:8:16: error: member ‘std::string <unnamed class>::integer’ with copy assignment operator not allowed in anonymous aggregate
s_int.h:14:2: error: abstract declarator ‘<unnamed class>’ used as declaration
   14 | };
      |  ^
s_int.cpp:5:17: error: expected id-expression before ‘(’ token
    5 |     s_int::s_int(std::string inp)
      |                 ^
s_int.cpp:9:17: error: expected id-expression before ‘(’ token
    9 |     s_int::s_int(const s_int &inp)
      |                 ^
s_int.cpp:13:47: error: ‘void operator=(const string&)’ should have been declared inside ‘::’
   13 |     void s_int::operator = (const string &inp )
      |                                               ^
s_int.cpp:13:15: error: ‘void operator=(const string&)’ must be a nonstatic member function
   13 |     void s_int::operator = (const string &inp )
      |               ^~
s_int.cpp:17:46: error: ‘void operator=(const int&)’ should have been declared inside ‘::’
   17 |     void s_int::operator = (const s_int &inp )
      |                                              ^
s_int.cpp:17:15: error: ‘void operator=(const int&)’ must be a nonstatic member function
   17 |     void s_int::operator = (const s_int &inp )
      |               ^~
s_int.cpp:21:29: error: expected constructor, destructor, or type conversion before ‘(’ token
   21 |     s_int s_int::operator + (s_int inp )
      |                             ^
  • `s_int` is both the include guard and the class name. I suggest using ALL_CAPS for macros. – al3c Aug 20 '20 at 16:46
  • You also need to include `s_int.h` in `main.cpp` if you want to use things from `s_int.h` in `main.cpp` – NathanOliver Aug 20 '20 at 16:47
  • @al3c Thanks, your suggestion worked. That's why I am curious about macros? – saaransh garg Aug 20 '20 at 16:51
  • Be careful with `#include `. In fact, [prefer not to use it.](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h). `Using namespace std;` [can also be harmful](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). Putting the two together is like playing Russian Roulette. It can drop bugs on you almost randomly. – user4581301 Aug 20 '20 at 16:52
  • I have included it s_int.h, sorry it is a copy-paste error – saaransh garg Aug 20 '20 at 16:53

4 Answers4

1
#define s_int

will have the compiler replace the class name s_int with empty string and will cause trouble.

Use another name to define for the include guard.

Using

#pragma once

instead is also good if this is supported in your environment.

Also you have to add #include "s_int.h" to main.cpp as @NathanOliver says.

MikeCAT
  • 61,086
  • 10
  • 41
  • 58
1

Macros are very simple text substitution. Everywhere the macro's identifier is found, whether it makes sense to do it or not, the identifier is replaced by whatever follows the identifier. So when you

#ifndef s_int 

everywhere you have s_int in the code, it's replaced with nothing. That means

s_int integer;

turns into

integer; 

and the compiler has no idea what to do with that.

class s_int

becomes

class

making an unnamed class definition. Chaos ensues if you try to use the now-nameless class.

You need to make sure macros are used carefully. Because of this many coding conventions require macros to be all UPPERCASE to make them stand out.

In the case of an Include Guard, the guard must be completely unique. If you reuse the identifier in your code, you get the sort of unexpected text substitutions you've seen in this code. If you have multiple headers guarded by the same identifier, the first use of the guard will block all other headers also using it. This is a very bad scene.

It can be mitigated with

#pragma once

if once is supported by your compiler, and most major compilers do support once, but if it's not supported #pragmas are allowed to be silently discarded, so you may not even know your headers aren't protected. In addition, sufficiently complicated project structures can fool once

user4581301
  • 29,019
  • 5
  • 26
  • 45
0

Have you thought putting the #include "s_int.h" in the main class?

0

I made few changes in your code.
I removed the unnecessary references, which are not required, for example take the overloading of = operator, we don't need it as we don't intend to change the arguments which are given.
We don't need to initialize string integer; as we implement constructor for it.
You should also consider, how we define macros #ifndef and #define in header files.
Combined you header file and it's methods implementation. s_int.h

#include <bits/stdc++.h>
#ifndef S_INT_H
#define S_INT_H
using namespace std;
class s_int
{
    public:
        string integer;
        s_int(std::string inp = "")
        {
            this->integer = inp;
        }
        s_int(const s_int *inp)
        {
            integer = inp->integer;
        }
        void operator=(const string inp)
        {
            this->integer = inp;
        }
        void operator= (const s_int inp)
        {
            this->integer = inp.integer;
        }
};
#endif

main.cpp

#include "s_int.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
    s_int integer;
    integer = "11111111111111111111111111111111111";
    s_int integer1(integer);
    cout << integer.integer << "\n";
    cout << integer1.integer << "\n";
}

Hope it helps, you to think in a proper way of writing classes in cpp.

dukeforever
  • 174
  • 7