2013-07-12 2 views
0

Я только начинаю снова посещать C++ после того, как не использовал этот язык более года, поэтому, пожалуйста, будьте терпеливы.Передача объектов класса по ссылке

У меня есть класс с методом, который ссылается на объект другого класса в качестве аргумента. Код довольно много выглядит следующим образом: (full code on pastebin)

//Entity.h 
namespace xe {  
class Entity {...} 
} 

//Component.h 
#include "entity.h" 

class Entity; 
namespace xe{ 
class Component 
{ 
    public : 
    void set_parent(Entity&); 
    private : 
    Entity* m_parent; 
} 
} 

//Component.cpp 
#include "component.h" 

xe::Component::set_parent(Entity& entity) { m_parent = &entity;} 

//Main.cpp 
#include "Entity.h" 
#include "Component.h" 
int main() 
{ 
    Entity entity(1 /*id*/); 
    Component comp; 
    comp.set_parent(entity); 
} 
} 

Этот код вызывает следующую Ошибка компиляции (Visual Studio)

error c2664:xe::Component::set_parent(Entity&) : cannot convert parameter 1 from xe::Entity to Entity& 

Между тем следующие пробеги кода и компилирует прекрасно

void square(int& i) 
{ 
    i *= i; 
} 
int main() 
{ 
    int number = 2; 
    square(number); 
    std::cout<<number; 
} 

Теперь, как я уже сказал, я не эксперт на C++, но для меня единственная разница между этими двумя функциями заключается в том, что square() принимает ссылку на примитивный тип данных (int), а do _something() принимает ссылку на экземпляр класса. Я не мог найти ничего о передаче объектов класса по ссылке, и я уже пробовал несколько альтернатив (делая ссылку const, явно создавая переменную типа Bar & и передавая ее методу), но ничего не работало, поэтому я думал, что буду спросите здесь.

+6

Ваш код должен быть другим. Это компилируется, как только вы исправляете очевидные проблемы. – chris

+2

[Как @chris написал] (http://coliru.stacked-crooked.com/view?id=cd9dbcfab91d7ffce4405c9247ecb6cf-9a9914b3e2b7ed07c206d6accecccdb6) –

+2

[Как @AndyProwl написал, с другой IDE] (http://ideone.com/uLUi8k) –

ответ

2

Проблема заключается линия

class Entity; 

Это говорит компилятору, что существует класс Entity в глобальном масштабе. Этот класс отличается от класса Entity, который вы определяете в пространстве имен. main() находится в глобальном пространстве имен и, таким образом, использует декларацию forward. Тем не менее, линия

comp.set_parent(entity); 

пытается передать объект этого глобального класса в области видимости функции, определенной в пространстве имен, которые, следовательно, ожидает объект класса в пределах этого пространства имен.

Чтобы это исправить, вам нужно удалить строку с упреждающим объявлением и изменить при создании экземпляра entity в

xe::Entity entity(1 /*id*/); 

Edit: Был ряд других пространств имен/сферу проблем, связанные в коде, версия ниже компилируется без ошибок. Я хотел бы предложить внимательно изучить каждую полученную вами ошибку, а затем о том, какие изменения я внес в эту позицию, потому что вам абсолютно необходимо научиться читать эти сообщения об ошибках при программировании на C++.

//Entity.h 
#pragma once 
#include<memory> 
#include<list> //necessary to use std::list 

namespace xe { 
    class Component; //must be inside namespace xe 

    class Entity { 
    public : 
     Entity(unsigned int); 
     std::list<std::unique_ptr<Component>> m_components; 
     void add_component(Component&); 
    private : 
     unsigned int m_id; 
    }; 
} 

//Entity.cpp 
#include "Entity.h" 

xe::Entity::Entity(unsigned int id) { //the name needs to reference the constructor _within_ the class, not the class itself 
    m_id = id; 
} 

void xe::Entity::add_component(xe::Component& component) { //Never forget the return type (unless you are writing a constructor/destructor, which do not have a return type. Also, component was misspelled... 
    m_components.push_back(std::unique_ptr<Component>(&component)); 
} 

//Component.h 
#pragma once 
#include "Entity.h" 
//class Entity; //Unnecessary, it's already defined within Entity.h. 
namespace xe { 
    class Component { 
     public : 
      void set_parent(xe::Entity&); 

     private : 
      xe::Entity* m_parent; 
    }; 
} 

//Component.cpp 
#include "Component.h" 
void xe::Component::set_parent(Entity& parent) { //Same problem as with the function above. 
    m_parent = &parent; 
} 

//main.cpp 
int main() { 
    xe::Entity entity(1); //main is not within the namespace, nor does it use it, so you need the scope resolution operator here. 
    xe::Component comp; //as above 
    entity.add_component(comp); 
    comp.set_parent(entity); //No error anymore... 
} 
+0

Или добавьте свою декларацию вперед в пространство имен xe. – biocomp

+0

@biocomp: Но тогда мне кажется, что noop, поскольку Component.h уже включает Entity.h. – cmaster

+0

Когда я удаляю прямое объявление, почти каждая строка в компоненте.h вызывает ошибки компиляции, большинство из которых даже не имеют смысла, как «отсутствующий тип спецификатора - int предполагается» в xe :: Entity * m_parent; – Max

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