2013-11-13 3 views
1

Я хочу поставить две классы в один файл заголовка. Один базовый класс, а второй выведенно этот базовый класс, что я имею в виду что-то вроде этого:Базовый и производный класс в одном заголовке

class Drawable{ 
public: 

    Drawable(); 

    void setPosition(math::Vector3 position); 

    void draw(); 

}; 

class Box: public Drawable{} ; 

Но я получаю ошибку «неопределенная ссылка на` Drawable :: Drawable()»». В исходном файле у меня есть:

class Drawable { 
public: 
    math::Vector3 position; 
    math::Vector3 rotation; 

    Drawable() { 
     position = math::Vector3(1.0, 1.0, 1.0); 
     rotation = math::Vector3(0.0, 0.0, 0.0); 
    } 

    void setPosition(math::Vector3 position) { 
     this->position = position; 
    } 

    void draw() { 
    } 
}; 

class Box: public Drawable { 
public: 
    void draw() { 

     glBegin(GL_TRIANGLES); 
     drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f)); 
     drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f)); 
     drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f)); 

     drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f)); 
     drawPoint(this->position + math::Vector3(1.0f, 1.0f, -1.0f)); 
     drawPoint(this->position + math::Vector3(1.0f, -1.0f, 1.0f)); 
     glEnd(); 
    } 
}; 

Так что мне кажется, невозможно сделать это, так как образовавшаяся класс в заголовке уже не знает о конструкторе базового класса. Я прав?

ответ

3

Вам нужно сделать что-то вроде этого:

example.h

class Drawable 
{ 
    public: 

    Drawable(); 

    void setPosition(math::Vector3 position); 

    virtual void draw(); 

    math::Vector3 position; 
    math::Vector3 rotation; 
}; 

class Box: public Drawable 
{ 
    public: 
    virtual void draw(); 
}; 

example.cpp

#include "example.h" 

Drawable::Drawable() { 
    position = math::Vector3(1.0, 1.0, 1.0); 
    rotation = math::Vector3(0.0, 0.0, 0.0); 
} 

void Drawable::setPosition(math::Vector3 position) { 
    this->position = position; 
} 

void Drawable::draw() { 
} 

void Box::draw() { 

    glBegin(GL_TRIANGLES); 
    drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f)); 
    drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f)); 
    drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f)); 

    drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f)); 
    drawPoint(this->position + math::Vector3(1.0f, 1.0f, -1.0f)); 
    drawPoint(this->position + math::Vector3(1.0f, -1.0f, 1.0f)); 
    glEnd(); 
} 

Заголовок определяет:

  • Constructor/Destructor подпись
  • переменных члены
  • членов сигнатуры функции

Источник определяет

  • Конструктор/деструктор реализации
  • реализация функции члена

N ote: Используйте оператор разрешения области видимости ::, чтобы обратиться к членам класса.

+0

Не имеет смысла иметь пустое определение 'draw' в базовом классе и НЕ сделать его' virtual'. –

+0

@KirilKirov Я только что ответил на вопрос, реализация не в моем бизнесе. – HAL

+0

ничья будет виртуальной, это неважно в текущей точке – spectre

1

Вы бы реализовать свои методы в исходном файле так:

void Drawable :: setPositon(...){ //do stuff }; 

Вы объявляете новый класс с таким же именем, чем в заголовке!

2
  1. Все данные (например, math::Vector3 position;) ДОЛЖНЫ быть определены ТОЛЬКО в файле заголовка, а не в cpp.
  2. Определение метода в файле CPP является: return_type class_name::function_name (parameters) { ... }
  3. draw должны быть в вашем случае virtual. Даже, может быть, чистый виртуальный (например, void draw() = 0; в базовом классе и объявленный и реализованный в производном).

Пример:

/////////////////////////////////////////// 
// header 
class A 
{ 
public: 
    A(); 
    void f(); 
private: 
    int x; 
}; 

/////////////////////////////////////////// 
// cpp 
A::A() 
{ 
    /* constructor impl */ 
} 

void A::f() 
{ 
    /* impl */ 
} 
0

также, видя, как у вас есть функция сеттера для вашего position члена, вероятно, вы должны сделать его закрытым, и объявить & определить поглотитель, а также:

class Drawable{ 
private: 
    math::Vector3 position; 
    math::Vector3 rotation; 
public: 
    Drawable(); 
    void setPosition(math::Vector3 position); 
    math::Vector3 getPosition(); 
    void setRotation(math::Vector3 rotation); 
    math::Vector3 getRotation(); 
    void draw(); 
}; 

с вашей текущей реализацией, вызов сеттера будет несколько избыточным, поскольку вы могли бы просто ccess элемент непосредственно, а не используя функцию setter:

Drawable d; 
d.position = math::Vector3(0,0,0);  //both do the 
d.setPosition(math::Vector3(0,0,0)); //same thing 
Смежные вопросы