2009-07-07 4 views
2

, чтобы создать экземпляр другого класса из класса, даже если класс, в котором я хочу иметь экземпляр, объявлен следующим классом, из которого я создаю экземпляр. Так же, как в C# и Java.это возможно в C++?

Спасибо

ответ

1

Несомненно. Вам просто нужно форвардное объявление. Нечто подобное работает просто отлично:

#include <iostream> 

class B; 

class A { 
public: 
    void hello(B &b); 
    void meow(); 
}; 

class B { 
public: 
    void hello(A &a); 
    void woof(); 
}; 

void A::hello(B &b) { b.woof(); } 
void A::meow() { std::cout << "Meow!" << std::endl; } 

void B::hello(A &a) { a.meow(); } 
void B::woof() { std::cout << "Woof!" << std::endl; } 

int main() { A a; B b; a.hello(b); b.hello(a); return 0; } 

Ключевым моментом здесь является то, что вы можете использовать только указатели или ссылки на класс, пока он не будет полностью определена. Поэтому в примере, который я дал, метод hello() в A может быть , объявленный, чтобы получить ссылку на B, хотя мы не определили B в точке. Однако после определения B определение метода A :: hello() может свободно использовать B по своему усмотрению.

+0

эй это действительно помогло! Спасибо – 2009-07-07 06:29:40

+1

«вы можете использовать указатели или ссылки только на класс, пока он не будет полностью определен». Насколько я знаю, вы также можете передавать классы по значению и из функций ... – SadSido

+0

Где награда за _deciphering_ этот вопрос? – bobobobo

1

Я думаю, вы имеете в виду, чтобы сделать что-то вроде этого:

class B; //Forward declaration 

class A 
{ 
    private: 
    B b; 
}; 


class B 
{ 

}; 

Это не возможно в C++ как компилятор должен знать SizeOf (B) при компиляции класса А.

в качестве решения, что вы можете сделать, это:

class B; //Forward declaration 

     class A 
     { 

      public: 
      A(); 
      ~A(); 

      private: 
      B* m_pB; //Store a pointer to B 

     }; 


     class B 
     { 

     }; 

A::A() 
{ 
    m_pB = new B; //Create an instance of B 
} 

A::~A() 
{ 
    delete m_pB; //Explictly deallocate the memory. 
    m_pB = NULL; 
} 
+0

да, я знаю это. но что, если я хочу получить доступ к общедоступной переменной или функции этого класса? – 2009-07-07 05:28:20

+0

Но противоположное (с A чуть ниже B) будет компилироваться отлично. –

+0

@maxx: Тем не менее это невозможно, поскольку компилятор просто знает, что есть что-то, называемое классом B, с использованием форвардного объявления, но оно не имеет представления о его содержимом. – Naveen

0

После того как вы вперед decla re B в заголовке, вы можете использовать его в файле .cpp без проблем для доступа к общедоступным переменным и методам.

+0

, можете ли вы дать мне рабочий пример C++. Спасибо – 2009-07-07 06:00:07

2

Вы можете использовать форвардное объявление для некоторых целей, но вам нужно будет иметь полный тип всякий раз, когда вы его фактически используете. Было бы целесообразно сделать вопрос более конкретным относительно того, чего вы действительно хотите достичь, поскольку могут быть более простые подходы к вашей проблеме (если порядок важен, это может указывать на круговую зависимость между классами A и B, и это обычно не так хорошо).

class B; 
class A 
{ 
public: 
    A(B b, B* bp, B& br) : bp_(bp), br_(br) {} // ok, incomplete types can be used as argument types 
    B f() 
// { return B(); } // nok: cannot create objects of incomplete type 
    ; 
    B* f2() { return bp_; } // ok 
    B& f3() { return br_; }; // ok 
    void g() 
// { bp_->g(); br_.g(); } // nok: cannot call methods of an incomplete type 
    ; 
    void g(B const & b) 
// { b.g(); } // nok: cannot call methods of an incomplete type 
private: 
    B * bp_; // ok (also const version) 
    B & br_; // ok (also const version) 
// B b_; // nok: B must be a complete type here 
}; 
class B { // A is complete, any use is correct here 
    void g() {} 
}; 
// From here on, B is a complete type and can be used in any possible way 
B A::f() { 
    return B(); // ok, now B is complete 
} 
void A::g() { 
    br_.g(); // ok, B is complete here 
    bp_->g(); // ok, B is complete here 
} 
void A::g(B const & b) { 
    b.g(); 
} 
Смежные вопросы