C ++ Новые объекты с несколькими классами - PullRequest
0 голосов
/ 07 марта 2012

Итак, у меня есть один основной файл и два класса: класс отображения и класс задания.

То, чего я хочу достичь, - это чтобы основной класс мог вызывать класс отображения, кака также интерфейс с классом задания, НО я также хочу, чтобы класс задания мог вызывать методы из класса Display и отправлять параметры в класс отображения.

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

Я также пытался пройтиобъекты Job / Display из main, но это не сработало с тем, что я хочу сделать, так как в моем заголовке я уже определил новый объект.

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

Main.cpp

 int main(){
    Display display;
    Job job;
    job.init();
    display.test();
    return 0;
}

Display.cpp

 void Display::test(){
     std::cout << "testing.." << std::endl;
 }

 void Display::test2(std::string ttt){
     Job job; //Do not want to create a whole new object here
     std::cout << "testing3333...." << job.getThree() << std::endl;
     std::cout << "testing2222...." <<  ttt << std::endl;
 }

Job.cpp

 void Job::init(){
      Display disp2; //I do not want to create a whole new object here, but I can't fix this
      disp2.test2("from Job");
 }

 std::string Job::getThree(){
       return "test3";
 }

Job.h

class Job{
private:
    Display disp; // Do not want a new object here as well
public:
    void init();
    std::string getThree();
};

Ответы [ 3 ]

3 голосов
/ 07 марта 2012

Вам нужно передать указатель Job на Display, и наоборот, чтобы они знали друг о друге, например:

Main:

#include "Display.h"
#include "Job.h"

int main()
{ 
    Display display; 
    Job job; 
    display.init(&job);
    job.init(&display); 
    display.test(); 
    return 0; 
} 

Display.h:

class Job;

class Display
{
private:
    Job *_job;
public:
    Display();
    void init(Job *job);
    void test();
    void test2(const std::string &ttt);
};

Display.cpp:

#include "Display.h"

Display::Display()
    : _job(NULL)
{
}

void Display::init(Job *job)
{
    _job = job;
}

void Display::test()
{ 
    std::cout << "testing.." << std::endl; 
} 

void Display::test2(const std::string &ttt)
{ 
    std::cout << "testing3333...." << _job->getThree() << std::endl; 
    std::cout << "testing2222...." << ttt << std::endl; 
} 

Job.h:

class Display;

class Job
{
private:
    Display *_display;
public:
    Job();
    void init(Display *display);
    std::string getThree();
};

Job.cpp:

#include "Job.h"

Job::Job()
    : _display(NULL)
{
}

void Job::init(Display *display)
{ 
    _display = display;
    _display->test2("from Job"); 
} 

std::string Job::getThree()
{ 
    return "test3"; 
} 

Учитывая упомянутые вами требования, Display не обязательно должен помнить Job, только Job должен помнить Display, чтобы вы могли сделать что-то подобное в качестве альтернативы:

Main:

#include "Display.h"
#include "Job.h"

int main()
{ 
    Display display; 
    Job job;
    job.init(&display); 
    display.test(); 
    return 0; 
} 

Display.h:

class Job;

class Display
{
public:
    void test();
    void test2(Job *job);
};

Display.cpp:

#include "Display.h"

void Display::test()
{ 
    std::cout << "testing.." << std::endl; 
} 

void Display::test2(Job *job)
{ 
    std::cout << "testing3333...." << job->getThree() << std::endl; 
} 

Job.h:

class Display;

class Job
{
private:
    Display *_display;
public:
    Job();
    void init(Display *display);
    std::string getThree();
};

Job.cpp:

#include "Job.h"

Job::Job()
    : _display(NULL)
{
}

void Job::init(Display *display)
{ 
    _display = display;
    _display->test2(this); 
} 

std::string Job::getThree()
{ 
    return "test3"; 
} 
0 голосов
/ 07 марта 2012

Вам нужно узнать о ссылках и указателях в C ++.

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

Вот основной способ использования обоих:

int i = 0;

int& refToI = i; // create a reference to i
int* ptrToI = &i; // create a pointer to i

int& anotherRef; // invalid, references must be initialized;
int* anotherPtr; // valid, points to garbage data, better set it to NULL though

refToI = 1; // i has been changed
*ptrToI = 1; // i has been changed, the "*" operator means "content pointed by"

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

Вот несколько примеров в вашем случае:

// Solution 1 take a reference to the objet in the function using it

class Job; // tells the compiler that there's a Job class somewhere.

class Display
{
public:
    void DoWork(Job& job) {
        // write this in the CPP file, I am using a shortcut for the sake of brevity
        job.DoSomething();
    }
};

// usage:
Display display;
Job job;
display.DoWork(job);



// Solution 2, carry the reference (or pointer) inside the class using it

class Job; // tells the compiler that there's a Job class somewhere.

class Display
{
public:
    Display(Job& job) // !! job must live at least as long as display
        : _job(job)
    { }

    void DoWork() {
        // write this in the CPP file, I am using a shortcut for the sake of brevity
        _job.DoSomething();
    }

private:
    Job& _job;
};


// Usage:
Job job;
Display display(job); // job and display have the same lifetime, OK
display.DoSomething();

Примечание

Существует дискуссия о том, следует ли вам использовать указатели или ссылки. Я думаю, что сейчас это немного сложнее для вас. Эмпирическое правило: используйте ссылки, когда время жизни хорошо известно, используйте умные указатели, когда их нет, или при использовании new.

.
0 голосов
/ 07 марта 2012

У вас, похоже, есть основная проблема ООП.Вот несколько вопросов, которые могут привести вас в правильном направлении.

Сколько экземпляров каждого класса вам нужно для вашей программы?

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

  1. Если вам нужен ровно один экземпляр обоих классов, сделайте их singleton , и у обоих будет доступдруг с другом, просто извлекая экземпляр singleton.

  2. Если вам нужен, скажем, один экземпляр отображения и несколько экземпляров задания, вы захотите сохранить экземпляры Job в контейнерек которому один экземпляр Display имеет доступ.Вы захотите сделать Display a singleton , чтобы к нему можно было получить доступ по желанию.

  3. Если вам нужно несколько экземпляров обоих, вам понадобится явно связать тех, кто должен работать вместе, путем передачи уже созданного объекта в конструктор другого.

Подумайте об этом:

Display d1, d2;
Job j1(&d1), j2(&d2); // make sure not to copy the displays!

и в конструкторе Job:

Job(Display *display): display(display) {
    display->setJob(this);
}

Если для одного задания требуется несколько отображений, вам придется заменить один указатель display в задании на набор Display указатели и добавление соответствующих дисплеев в эту коллекцию вручную.


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

...