ghostmansd
ghostmansd

Reputation: 3455

C++: constructor with user-defined types

I'm trying to understand classes in C++ and develop some similar classes which I've seen in Python. Here is the code:

#include <iostream>
#include <cmath>
using namespace std;

/*============================================================================*/
/* Define types
/*============================================================================*/
class none_type;
class bool_type;
class int_type;
struct identifier;

/*============================================================================*/
/* Define none type
/*============================================================================*/
class none_type {
  public:
    none_type()                  { /* constructor */ };
    ~none_type()                 { /* destructor */ };
}; /* none_type */

/*============================================================================*/
/* Define bool type
/*============================================================================*/
class bool_type {
  private:
    bool base;
  public:
    bool_type()                  { base = false; };
    ~bool_type()                 { /* destructor */ };
    bool_type(bool init)         { base = bool(init); };
    bool_type(int init)          { base = bool(init); };
    bool_type(long init)         { base = bool(init); };
    bool_type(float init)        { base = bool(init); };
    bool_type(double init)       { base = bool(init); };
    bool_type(bool_type init)    { base = bool(init.base); };
    bool_type(int_type init)     { base = bool(init.base); };
    int get()                    { cout << base << endl; };
}; /* bool_type */

/*============================================================================*/
/* Define int type
/*============================================================================*/
class int_type {
  private:
    long base;
  public:
    int_type()                   { base = 0; };
    ~int_type()                  { /* destructor */ };
    int_type(bool init)          { base = long(init); };
    int_type(int init)           { base = long(init); };
    int_type(long init)          { base = long(init); };
    int_type(float init)         { base = long(init); };
    int_type(double init)        { base = long(init); };
    int_type(bool_type init)     { base = long(init.base); };
    int_type(int_type init)      { base = long(init.base); };
    int get()                    { cout << base << endl; };
}; /* int_type */

When I try to compile it, g++ tells that all my constructors which use my own types are invalid. Could you explain what's wrong, please? I've defined class prototypes, what else should I do? Thanks in advance!

Upvotes: 1

Views: 878

Answers (3)

Kerrek SB
Kerrek SB

Reputation: 476980

It's hard to give specific advice short of "learn C++", but here's how your classes could be designed in "normal" C++:

class int_type;

class none_type { };

class bool_type
{
    bool base;
public:
    bool_type() : base() { }
    explicit bool_type(bool init) : base(init) { }
    explicit bool_type(int_type const &);

    void print() const { std::cout << base << std::endl; }
    bool get() const { return base; }
};

class int_type
{
    int base;
public:
    int_type() : base() { }
    explicit int_type(int init) : base(init) { }
    explicit int_type(bool_type const & init) : base(init.get() ? 1 : 0) { }

    void print() const { std::cout << base << std::endl; }
    int get() const { return base; }
};

inline bool_type::bool_type(int_type const & init) : base(init.get()) { }

Upvotes: 1

Olaf Dietsche
Olaf Dietsche

Reputation: 74018

G++ already tells you, what's wrong:

error: invalid constructor; you probably meant 'bool_type (const bool_type&)'

Instead of bool_type (bool_type) you must use bool_type (const bool_type&). The reason for this is, if you pass an object by value the compiler uses the copy constructor to put it on the stack. So, in order to pass the bool_type to the copy constructor bool_type(bool_type), it must use the copy constructor itself. That is not possible.

Same goes for int_type(int_type).

In constructor 'bool_type::bool_type(int_type)': error: 'init' has incomplete type

At this point, G++ has no idea of how the int_type looks like. Since it doesn't know that int_type has a base member, it cannot use it. Just declare the constructor:

bool_type(int_type init);

and define it after the declaration of int_tpye:

....
class int_type {
....
};

...
inline bool_type(int_type init) { base = bool(init.base); }

When you have larger objects, it is good advise to use pass them by reference, since passing by value means copying the objects on the stack. This is much more expensive (for large objects) than just passing a reference to this large object. For small objects, this doesn't matter that much.

And the last error:

In constructor 'int_type::int_type(bool_type)': error: 'bool bool_type::base' is private

You have declared the member base in bool_type as private:. This means, only bool_type is allowed to access this member. In order to get hold of base you must use the access method get():

int_type(bool_type init)     { base = long(init.get()); }

Analogous, you must define:

inline bool_type(int_type init) { base = bool(init.get()); }

Finally, look at or c++ and follow the book list. The C++ FAQ is also pretty decent.

Edit: I missed, that your get() methods aren't accessors at all. They should be defined as:

class bool_type {
public:
    bool get() const { return base; }
...
};

Same for int_type::get()

int get() const { return base; }

Upvotes: 2

PiotrNycz
PiotrNycz

Reputation: 24382

This constructor:

bool_type(int_type init)     { base = bool(init.base); };

is invalid because int_type is incomplete at this point.

You must move this constructor implementation out of the class definition, to the point where int_type is complete:

class bool_type {
  bool_type(int_type init);
};
class int_type {};
inline bool_type::bool_type(int_type init)     { base = bool(init.base); };

Another problem is with your constructor which pretends to be copy constructor:

bool_type(bool_type init)    { base = bool(init.base); };

Here you have infinite recursion - because init parameter is a copy - so this very constructor must be called to make this copy, but this next call of this constructor has its own init parameter which must be copied and so on to infinity or to stack limit...

The proper definition of copy constructor is as follows:

bool_type(const bool_type& init)    { base = bool(init.base); };

Const reference must be used, however in this very you can rely on compiler - it will generate copy constructor for you - so just remove it at all.

Upvotes: 3

Related Questions