2012-10-28 4 views
1

Я пытаюсь понять классы на C++ и разработать некоторые подобные классы, которые я видел в Python. Вот код:C++: конструктор с пользовательскими типами

#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 */ 

Когда я пытаюсь скомпилировать его, g++ говорит, что все мои конструкторы, которые используют свои собственные типы являются недействительными. Не могли бы вы объяснить, что случилось, пожалуйста? Я определил прототипы классов, что еще мне делать? Заранее спасибо!

+0

Вам не нужно ставить ',' в конце определения функции. И узнайте о списке инициализации конструктора ... –

+0

Я удалил точки с запятой; который ничего не решает. Кажется, что не так много ситуаций, когда вы __must__ удаляете точку с запятой в конце строки в C/C++. – ghostmansd

+1

Вы вводите в заблуждение «определения» и «декларации». –

ответ

2

G ++ уже говорит вам, что случилось:

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

Вместо bool_type (bool_type) вы должны использовать bool_type (const bool_type&). Причина этого в том, что если вы передаете объект по значению, компилятор использует конструктор копирования, чтобы поместить его в стек. Итак, чтобы передать bool_type в конструктор копирования bool_type(bool_type), он должен использовать сам конструктор копирования. Это невозможно.

То же самое касается int_type(int_type).

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

На данный момент, G ++ не имеет ни малейшего представления о том, как int_type выглядит. Поскольку он не знает, что int_type имеет предмет base, он не может его использовать.Просто объявить конструктор:

bool_type(int_type init); 

и определить его после объявления int_tpye:

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

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

Если у вас есть большие объекты, хорошо советуют использовать передавать их по ссылке, так как проходя через значение копирование объектов в стеке. Это намного дороже (для больших объектов), чем просто передача ссылки на этот большой объект. Для небольших объектов это не имеет большого значения.

И последняя ошибка:

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

Вы объявили член base в bool_type в private:. Это означает, что только bool_type имеет доступ к этому члену. Для того, чтобы завладеть base вы должны использовать метод доступа get():

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

Аналоговая, вы должны определить:

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

Наконец, посмотрите на или c++ и следовать список книг. C++ FAQ также довольно приличный.

Редактировать: Я пропустил, что ваши методы get() не являются аксессуарами. Они должны быть определены как:

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

То же самое для int_type::get()

int get() const { return base; } 
3

Этот конструктор:

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

является недействительным, поскольку INT_TYPE является неполным в этой точке.

Вы должны переместить эту реализацию конструктор из определения класса, до точки, где INT_TYPE является полным:

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

Другая проблема связана с конструктором, который претендует на конструктор копирования:

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

Здесь у вас есть бесконечная рекурсия - потому что параметр init - это копия, поэтому этот самый конструктор должен быть вызван, чтобы сделать это c опировать, но следующий вызов этого конструктора имеет свой собственный init параметр, который должен быть скопирован и так далее до бесконечности или складывают предел ...

Правильное определение конструктора копирования заключается в следующем:

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

Ссылка на константу должна использоваться, однако в этом вы можете положиться на компилятор - он создаст для вас конструктор копий - так что просто удалите его вообще.

1

Это трудно дать конкретные советы не хватает «узнать C++», но вот как ваши классы могут быть разработаны в «нормальном» 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()) { } 
+0

' base' является закрытым в обоих случаях. Поэтому вам нужен оператор доступа или оператор преобразования, чтобы использовать их в другом конструкторе. –

+0

@OlafDietsche: Хорошая точка, исправлена. Благодаря! –

Смежные вопросы