I am not sure if the title of my question is correct and clear enough. I am not a very experienced software engineer.
I have been preparing a 3D geometry library which utilizes handles as i dont want to use either delete operators or smart pointers. I have a number of classes which are involved in a class hierarchy (implementation inheritance): ReferenceBase, PointBase, Point2D, Point3D, VectorBase etc. For example, CoordSystem inherits from GeometryBase, PointBase inherits from ReferenceBase and LinePieceBase inherits from GeometryBase. I have corresponding handle classes for each: Handle_GeometryBase, Handle_Point2D, Handle_Plane etc. I implemented the library using handle objects (e.g. Handle_Point2D) instead of the original classes (e.g. Point2D). For example the project point method of Plane class is defined like:
Handle_Point3D Plane::project(const Handle_PointBase& point) {}
The handle classes have the same hierarchy reflected (e.g. Handle_VectorBase inherits from Handle_ReferenceBase). I could not utilize a generic class for the handles because of this inheritance. So, i have defined a handle class for each original class using macros. The handle classes are almost the same accept for a few details so i have defined three macros.
This is the architecture i have:
// Forward declarations for the handle classes
class Handle_Foo;
class Handle_Bar;
class Foo {
int a;
public:
Foo(int aa) : a{ aa } {}
/* copy/move ctors, assignments and dtor */
};
class Bar {
Handle_Foo f;
public:
Bar(const Handle_Foo& ff) : f{ ff } {}
/* copy/move ctors, assignments and dtor */
};
class Handle_Foo {
Foo* p;
public:
Handle_Foo() : p{} {}
Handle_Foo(Foo* pp) : p{ pp } {}
Handle_Foo(const Handle_Foo& rhs) : p{ new Foo{ *rhs.p } } {};
Handle_Foo(Handle_Foo&& rhs) noexcept : p{ rhs.p } { delete rhs.p; }
Handle_Foo& operator=(const Handle_Foo& rhs) {
p = new Foo{ *rhs.p };
return *this;
};
Handle_Foo& operator=(Handle_Foo&& rhs) noexcept {
p = rhs.p;
delete rhs.p;
return *this;
}
Foo* operator->() const { return p; }
~Handle_Foo() { delete p; }
Foo* Get() const noexcept { return p; }
void Set(Foo* pp) noexcept { p = pp; }
bool IsNull() const noexcept { return bool(p == nullptr); }
};
class Handle_Bar {
Bar* p;
public:
Handle_Bar() : p{} {}
Handle_Bar(Bar* pp) : p{ pp } {}
Handle_Bar(const Handle_Bar& rhs) : p{ new Bar{ *rhs.p } } {};
Handle_Bar(Handle_Bar&& rhs) noexcept : p{ rhs.p } { delete rhs.p; }
Handle_Bar& operator=(const Handle_Bar& rhs) {
p = new Bar{ *rhs.p };
return *this;
};
Handle_Bar& operator=(Handle_Bar&& rhs) noexcept {
p = rhs.p;
delete rhs.p;
return *this;
}
Bar* operator->() const { return p; }
~Handle_Bar() { delete p; }
Bar* Get() const noexcept { return p; }
void Set(Bar* pp) noexcept { p = pp; }
bool IsNull() const noexcept { return bool(p == nullptr); }
};
So the original classes requires the handle classes to be defined as you see.
The handle examples i saw on the internet or in the Stroustrup's book (c++ programming language) is defined with a template which calls the default copy and move ctors and the default dtor.
// Handle copy ctor for a template design
template<class T>
class Handle {
T* p;
public:
Handle(const Handle& rhs) : p{ new T{ *rhs.p } } {};
/* Other code */
};
However, my architecture requires the ctors, dtor and assignment operators to be defined.
// Handle copy ctor for my current design
class Handle_Bar {
Bar* p;
public:
Handle_Bar(const Handle_Bar& rhs) : p{ new Bar{ *rhs.p } } {};
/* Other code */
};
The copy ctor requires the copy ctor of Bar class to be defined due to p{ new Bar{ *rhs.p } }.
In summary, the original classes require the definition for the handle classes and the handle classes require the definition of copy/move ctors, asssinments and dtor for the original classes.
For this design pattern i recive the following error for the (Handle_Foo f) member defined in Bar class:
f uses undefined class Handle_Foo
Previously i had a different pattern. I have defined the handle classes in another header file like
Handles.h:
// Forward declarations for the original classes
class Foo;
class bar;
/* The same definitions for the handle classes as above */
Geometry.h
#include "Handles.h"
/* Definitions for the original clasases */
In this case, the original class definitions worked but for the copy/move ctors/assignments and dtor of the handle classes i recieved errors.
In the past i used a framework (Caesam) which used handle classes defined for each object which worked well. But the implementaation of the framework is not open source. Hence, i could not get the architecture they used.
Hence, how can i solve the error i mentioned above:
Error: f uses undefined class Handle_Foo
I have solved the problem. The framework I used Caesam actually uses OpenCascade (OCCT) library for the handles. OCCT can be downloaded from https://www.opencascade.com/. VS configuration procedure for OCCT is described in this video. Defining and implementation of a handle is as follows:
// The header file: Foo.hxx
#ifndef _Foo_HeaderFile
#define _Foo_HeaderFile
#ifndef _Standard_HeaderFile
#include <Standard.hxx>
#endif
#ifndef _Standard_Handle_HeaderFile
#include <Standard_Handle.hxx>
#endif
#ifndef _Standard_Type_HeaderFile
#include <Standard_Type.hxx>
#endif
#ifndef _Standard_Size_HeaderFile
#include <Standard_Size.hxx>
#endif
#ifndef _Standard_Transient_HeaderFile
#include <Standard_Transient.hxx>
#endif
#ifndef _FooBase_HeaderFile
#include "FooBase.hxx"
#endif
// Forward declaration of the class and the base class
class Foo;
class FooBase;
// Define the handle
DEFINE_STANDARD_HANDLE(Foo, FooBase)
class Foo: public FooBase
{
// Define the members, ctors, dtor and operators
// Define the RTTI
public:
DEFINE_STANDARD_RTTIEXT(Foo, FooBase)
}
#endif
All classes can be defined similarly. The implementation of RTTI should be performed after all definitions are done. So, its better to do RTTI implementation in cxx files.
// Foo.cxx
#include "Foo.hxx"
// Define RTTI
IMPLEMENT_STANDARD_RTTIEXT(Foo, FooBase)
// Implement the functions
Standard_Transient is the base class for the OCCT. Its better to create an abstract base class for your project inheritting from Standard_Transient
class AbstractBase : public Standard_Transient
{
}
class foo: public AbstractBase
{
}
Related
I am trying to implement the curiously recurring template pattern (CRTP) to access a member variable of a child class from the parent class, but I am getting a compilation error saying I am illegally referencing a non-static member variable.
#include <iostream>
template <typename Child>
class Parent
{
public:
int get_value()
{
return Child::m_value;
}
virtual ~Parent() = default;
};
class Child : public Parent<Child>
{
int m_value = 42;
friend class Parent<Child>;
};
int main()
{
Child child;
std::cout << child.get_value() << std::endl;
}
Error:
illegal reference to non-static member 'Child::m_value'
How can I properly access the member variable of the child class from within the parent class?
Is CRTP even the best/cleanest approach here?
Here is the correct way to access members of a CRTP derived class.
template <typename Child>
class Parent
{
public:
int get_value()
{
// Do NOT use dynamic_cast<> here.
return static_cast<Child*>(this)->m_value;
}
~Parent() { /*...*/ }; // Note: a virtual destructor is not necessary,
// in any case, this is not the place to
// define it.
};
// A virtual destructor is not needed, unless you are planning to derive
// from ConcreteClass.
class ConcreteClass : public Parent<ConcreteClass>
{
friend class Parent<ConcreteClass>; // Needed if Parent needs access to
// private members of ConcreteClass
// If you plan to derive from ConcreteClass, this is where you need to declare
// the destructor as virtual. There is no ambiguity as to the base of
// ConcreteClass, so the static destructor of Parent<ConcreteClass> will
// always be called by the compiler when destoying a ConcreteClass object.
//
// Again: a virtual destructor at this stage is optional, and depends on
// your future plans for ConcreteClass.
public:
virtual ~ConcreteClass() {};
private:
int m_value;
};
// only ConcreteClass needs (optionally) a virtual destructor, and
// that's because your application will deal with ConcretClass objects
// and pointers, for example, the class below is totally unrelated to
// ConcreteClass, and no type-safe casting between the two is possible.
class SomeOtherClass : Parent<SomeOtherClass> { /* ... */ }
ConcreteClass obj1;
// The assignment below is no good, and leads to UB.
SomeOtherClass* p = reinterpret_cast<ConcreteClass*>(&obj1);
// This is also not possible, because the static_cast from
// Parent<UnrelatedClass>* to UnrelatedClass* will not compile.
// So, to keep your sanity, your application should never
// declare pointers to Parent<T>, hence there is never any
// need for a virtual destructor in Parent<>
class UnrelatedClass {/* ... */ };
auto obj2 = Parent<UnrelatedClass>{};
As the concrete type ConcreteClass and its relation to Parent is known ate compile-time, a static_cast is sufficient to convert this from Parent<ConcreteClass>* to a ConcreteClass*. This provides the same functionality as virtual functions without the overhead of a virtual function table, and indirect function calls.
[edit]
Just to be clear:
template <typename Child>
class Parent
{
public:
int get_value()
{
// the static cast below can compile if and only if
// Child and Parent<Child> are related. In the current
// scope, that's possible if and only if Parent<Child>
// is a base of Child, aka that the class aliased by Child
// was declared as:
// class X : public Parent<X> {};
//
// Note that it is important that the relation is declared
// as public, or static_cast<Child*>(this) will not compile.
//
// The static_cast<> will work correctly, even in the case of
// multiple inheritance. example:
//
// class A {];
// class B {};
// class C : public A
// , public Parent<C>
// , B
// {
// friend class Parent<C>;
// int m_value;
// };
//
// Will compile and run just fine.
return static_cast<Child*>(this)->m_value;
}
};
[edit]
If your class hierarchy gets a bit more complex, the dispatching of functions will look like this:
template <typename T>
class A
{
public:
int get_value()
{
return static_cast<T*>(this)->get_value_impl();
}
int get_area()
{
return static_cast<T*>(this)->get_area_impl();
}
};
template <typename T>
class B : public A<T>
{
friend A<T>;
protected:
int get_value_impl()
{
return value_;
}
int get_area_impl()
{
return value_ * value_;
}
private:
int value_;
};
template <typename T>
class C : public B<T>
{
// you must declare all bases in the hierarchy as friends.
friend A<T>;
friend B<T>;
protected:
// here, a call to C<T>::get_value_impl()
// will effetively call B<T>::get_value_impl(),
// as per usual rules.
// if you need to call functions from B, use the usual
// syntax
int get_area_impl()
{
return 2 * B<T>::get_value_impl();
}
};
I want to enhance members of C++ classes so that assignment from/to them results in the call of a custom getter/setter.
Like
class Class
{
public:
int Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
}
and
Class Instance;
Instance.Member= 3; // Causes a call to SetMember(3);
int Data= Instance.Member; // Causes a call to GetMember();
I have found a way to force a function call upon member assignment, by turning the member type to a class holding a private value, and overloading the cast operator for reading and the assignment operator for writing.
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign) { Value= Assign; }
private:
int Value;
}
This works, but in a generic way, I cannot customize the getters/setters per member but only per data type.
Do you see a way to refine so that I can write different accessors for different members of the same type ?
Update:
I have now found a solution that satisfies my needs. The members that require a special setter are defined using a class that knows the hosting class:
template<class Parent> class WrapInt
{
public:
int operator=(const int Value) { (This->*Setter)(Value); return Value; }
operator int() { return Value; }
private:
int Value;
Parent* This;
void (Parent::*Setter)(int Value);
friend Parent;
};
Assigning such a member invokes the assignment operator, which calls a plain setter function via a pointer to method of the main class. The Get operation is implemented via the cast operator, which just returns the member value (the scheme might be enhanced to support custom getters, but I didn't need that).
This is pretty costly as every member takes an extra This pointer to the class instance and a pointer to the setter; these need to be initialized in the class constructor (if not, a crash is guaranteed).
So this takes some effort on the side of the class writer (initialization in the constructor), but then assigning to the member automatically invokes the setter, as I want.
class Class
{
public:
Class();
WrapInt<Class> Member;
private:
void SetMember(int Value); // TBD
}
Class::Class() { Member.This= this; Member.Setter= &Class::SetMember; }
On the side of the user,
Class Instance;
Instance.Member= 3; // Calls the setter SetMember
cout << Instance.Member;
that's it.
You could make your class WrapInt modifyable.
Option 1: At runtime, using a function object
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
std::function<void (int)> assign_callback;
}
In this variant, you would have to assign the correct callbacks in the constructor of the containing class:
class Container
{
WrapInt a, b, c;
Container ()
{
a.assign_callback = ...;
b.assign_callback = ...;
c.assign_callback = ...;
}
}
Option 2: At compile-time, using inheritance
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
virtual void assign_callback(int) = 0;
}
In this variant, you would inherit from WrapInt multiple times in the class body of the containing class
class Container
{
class WrapIntA : public WrapInt {
void assign_callback() { ... };
} a;
class WrapIntB : public WrapInt {
void assign_callback() { ... };
} b;
class WrapIntC : public WrapInt {
void assign_callback() { ... };
} c;
}
A modified version of your code:
class WrapInt
{
public:
WrapInt(std::function<int()> getter, std::function<void(int)> setter) :
getter(getter),
setter(setter)
{}
WrapInt(const WrapInt&) = delete;
WrapInt& operator =(const WrapInt&) = delete;
operator int() const { return getter(); }
void operator=(int value) { setter(value); }
private:
std::function<int()> getter;
std::function<void(int)> setter;
};
class Class
{
public:
Class() : Member([this](){ return this->GetMember();},
[this](int value) {SetMember(value); })
{}
WrapInt Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
};
Don't fight the language: C++ does not support get / set bindings to functions. You merely have to tolerate
Instance.Member() = 3;
and
int Data = Instance.Member();
Which you can provide by supplying a const function Member() that returns a const reference, and a non-const version that returns a non-const reference.
One criticism of C++ is the amount of boilerplate you need to write, especially if you need this for every member variable in your class. But really at that point, you are pretty much circumventing encapsulation entirely: you may as well make the members public unless your functions make consistency checks.
I have the following setup:
foo.h:
class A {
friend class B;
private:
A() {}
};
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
vector<A> myMember;
};
An object of A will never be exposed to any program including foo.h. The vector with A's is only there to help B in its computation adapter role. By making A's constructor private, I thought I could avoid other compilation units from using it, and it seems to work. However, the problem is in
foo.cpp
void B::computeResult(Result &r) {
MyCustomStorage<A> storage;
A *a = storage.allocate(); // error: "A::A() is private"
}
where part of MyCustomStorage looks like so:
template <typename T>
class MyCustomStorage {
T *allocate() {
...
T *ptr = new T[count]; // error: "A::A() is private"
...
}
};
But I thought since allocate() is called from a member function, this wouldn´t happen! How could I solve this?
Making A a friend to MyCustomStorage seems very spaghetti-codish. Making A a private nested class of B makes all sorts of help-classes in foo.cpp fail because "A is private".
So what would be the cleanest way to solve this?
SOLUTION
I ended up going with #potatoswatter 's second solution, with these appropriate changes:
foo.h
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
class A {
private:
A() {}
};
class Helper; // forward declared!
vector<A> myMember;
};
foo.cpp
class B::Helper {
int help(A& a) { return 42; } // no problem! Helper is a member of B
}
void B::computeResult(Result &r) {
MyCustomStorage<A> storage;
A *a = storage.allocate(); // no problem! A is a member of B
Helper h;
h.help(*a); // no problem!
}
It's not the constructor of A that is private, it's the entire class.
The best solution is to create a "private" namespace. C++ doesn't have namespace-level access protection, but it's reasonable to expect that users won't access an unfamiliar namespace.
namespace impl {
struct A {
A() {}
};
}
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
vector<impl::A> myMember;
};
Another approach is to make A a member of B. This offers "real" access protection at the expense of deeper nesting. I personally prefer the first solution, and to avoid nested classes.
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
struct A {
A() {}
};
vector<A> myMember;
};
Any helpers that need A would then need to be friends. There are various workarounds like nesting A in a base class with protected access, but really, namespace impl offers the least compromises.
IMHO, You have a couple options. You can either 1) Use the Pimpl idiom, or, 2) you can use forward declaration.
Pimpl Idiom Example:
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
class Impl;
Impl *pimpl;
};
And in your *.cpp file, you can define the Impl class and use it's guts.
class B::Impl {
public:
std::vector<A> stuff;
}
B::B() : pimpl(new Impl) {
}
B::~B() {
delete pimpl;
}
void B::AddObject(Object &o) {
pimpl->stuff.Fx(o);
}
You can also use a smart pointer for the Pimpl idiom, I just didn't here for the sake of clarity/brevity.
Forward declaration can also be used if A is in the same namespace as B
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
std::vector<class A*> myMember;
};
But this idiom is fundamentally different than your requirements and restricts you to using a pointer within your object myMember, which you may not want to do. Inline defining class A* is also a non-standard forward-declarative approach. Of course, use of smart pointers would reduce the possibility of memory-leaks at this location.
I have a set of classes (SubClassA, SubClassB, etc) that inherit from SuperClass. These classes have a myriad of methods that are exactly identical between the subclasses, except that they return a reference to *this (a.k.a. SubClassX&). The return type can't be deprecated to SuperClass& either, because then the subclass-specific functions and members wouldn't be accessible.
I'm looking for a short, clean way to implement this so that I don't have to replicate the method code in each subclass.
The best thing I've been able to come up with is something like this (pseudo-code), but I'm not sure if this would even work:
//methods.cpp
SUBCLASS& general_method_1() {return *this;}
SUBCLASS& general_method_2() {return *this;}
And then:
#define SUBCLASS SubClassA
class SubClassA : public SuperClass
{
#include "methods.cpp"
SubClassA& specific_method_1() {return *this;}
}
#define SUBCLASS SubClassB
class SubClassB : public SuperClass
{
#include "methods.cpp"
SubClassB& specific_method_2() {return *this;}
}
Not to mention this seems kind of hackish and difficult to interpret. Any ideas?
EDIT:
I should have mentioned that I will need to be able to polymorphically access the subclasses through pointers to SuperClass. For example, the following needs to be valid:
SuperClass* subclass[2];
subclass[0] = new SubClassA;
subclass[1] = new SubClassB;
CRTP.
template <class Derived> class Base
{
Derived& derived() { return static_cast<Derived&>(*this); }
};
class Derived1: public Base<Derived1>
{
};
class Derived2: public Base<Derived2>
{
};
In order to access things polymorphically, one needs to split Base in two:
class Base
{
public:
virtual ~Base() {}
// virtual Base& derived() = 0; -- note: this will NOT work!
};
template <class Derived> class BaseImpl : public Base
{
Derived& derived() { return static_cast<Derived&>(*this); }
};
class Derived1: public BaseImpl<Derived1>
{
};
class Derived2: public BaseImpl<Derived2>
{
};
int main()
{
Base* b[2] = { new Derived1, new Derived2 };
}
The way I would do it:
class Dystopia {
using This = Dystopia;
This& beHappy() {
// make me happy
return *this;
}
};
class Utopia : public Dystopia {
using This = Utopia;
This& beHappy() {
return static_cast<This&>(Dystopia::beHappy());
}
};
The main point here is that when you are in a derived class you can explicitly call the base method.
Note that the typedef is just a commodity (is not required).
As a sidenode: avoid macros in C++. Can’t emphasise this enough: Avoid macros!!. Armageddon will come in macros and good luck then debugging the End of the world.
I am going to suggest the following:
Create a .h file that contains one or more macros to declare the common functions.
Create a .h file that contains one or more macros to define the common functions.
Add the include file created in (1) in the class header files and use the macro(s) to declare the functions.
Add the include file created in (2) in the class .cc files and the use the macro(s) to define the functions.
Example:
DeclareFunctionsMacros.h
#define DECLARE_FUNCTIONS(THIS_CLASS) \
THIS_CLASS& general_method_1(); \
THIS_CLASS& general_method_2();
DefineFunctionsMacros.h
#define DEFINE_FUNCTIONS(THIS_CLASS) \
THIS_CLASS& THIS_CLASS::general_method_1() { return *this; } \
THIS_CLASS& THIS_CLASS::general_method_2() { return *this; }
SubClassA.h
#include "DeclareFunctionsMacros.h"
class SubClassA : public SuperClass
{
DECLARE_FUNCTIONS(SubClassA);
SubClassA& specific_method_1() {return *this;}
}
SubClassA.cc
#include "DefineFunctionsMacros.h"
DEFINE_FUNCTIONS(SubClassA)
This will allow you to alter definitions of the macros used in defining the functions without needing to recompile everything that #includes SubClassA.h.
It's not clear from your question whether all you require is to make use of covariant return types and a template.
For example:
class SuperClass
{
public:
virtual SuperClass& method() = 0;
};
class SpecificA : public SuperClass
{
public:
int specificMethodA();
};
class SpecificB : public SuperClass
{
public:
int specificMethodB();
};
template<class Specific>
class SubClass : public Specific
{
public:
virtual SubClass& method() { return *this; }
};
int main()
{
SubClass<SpecificA> scA;
SubClass<SpecificB> scB;
scA.method().specificMethodA();
scB.method().specificMethodB();
}
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!
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.
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 c++-faq 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; }
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()) { }