2010-10-14 2 views
4

В C++ можно вызвать функцию экземпляра до завершения конструктора этого экземпляра?C++: Можно ли вызвать функцию объекта до завершения конструктора?

например. если конструктор A создает экземпляр B и конструктор B вызывает одну из функций A.

+1

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

+0

@ Мартин, я задал общий вопрос нарочно. В моем конкретном случае детали являются утомительными и несущественными. Фактически после прочтения ответов я решил избежать этого и отделить процесс инициализации от логики «идти», которая начинает бизнес-логику. В ретроспективе это хорошая практика, которую я буду принимать дальше. – Jonathan

+0

Хорошая идея: потому что общие вопросы хорошо дают вам хорошие явные ответы? –

ответ

11

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

+3

Включено в это (но заслуживает внимания) то, что вы не должны вызывать виртуальные функции-члены от вашего конструктора, по крайней мере, не без понимания того, что произойдет.Поскольку любой производный класс еще не полностью сконструирован, вызов переопределенной виртуальной функции в конструкторе базового класса вызовет реализацию этой функции базового класса (и если функция базового класса является чистой виртуальной, вы получите ошибку времени выполнения). Поэтому лучше не называть _any_ виртуальные функции в конструкторе. – Gretchen

+0

@ Матвей: Действительно. Спасибо за это ценное дополнение! – sbi

4

Это очень возможно

class A; 
class B { 
public: 
    B(A* pValue); 
}; 

class A { 
public: 
    A() { 
    B value(this); 
    } 
    void SomeMethod() {} 
}; 

B::B(A* pValue) { 
    pValue->SomeMethod(); 
} 
1

Это возможно, а иногда и практически необходимо (хотя оно усиливает способность ненадлежащим образом выравнивать городской блок). Например, в C++ 98 вместо определения искусственного базового класса для общей инициализации в C++ 98 часто видят, что это делается с помощью функции init, вызываемой от каждого конструктора. Я не говорю о двухфазной конструкции, которая просто злая, но о факторизации общей инициализации.

C++ 0x обеспечивает переадресацию конструктора, которая поможет устранить проблему.

Для практики это опасно, нужно быть осторожным в отношении того, что инициализировано и нет. И для чисто формального в стандарте есть излишне неопределенная формулировка, которая может быть истолкована так, как будто объект действительно не существует до тех пор, пока конструктор не завершится успешно. Однако, поскольку эта интерпретация заставит UB использовать, например, функция init, чтобы отделить обычную инициализацию, что является обычной практикой, ее можно просто игнорировать.

Приветствия & НТН.,

-2

почему ты хочешь сделать это? Нет. Это невозможно сделать, поскольку вам нужен объект как один из его параметров. Реализация функции члена C++ и функция C - это разные вещи.

C++ код

class foo 
{ 
    int data; 
    void DoSomething() 
    { 
     data++; 
    } 
}; 


int main() 
{ 
    foo a;    //an object 
    a.data = 0;   //set the data member to 0 
    a.DoSomething(); //the object is doing something with itself and is using 'data' 
} 

Вот простой способ, как сделать это C.

typedef void (*pDoSomething)(); 
typedef struct __foo 
{ 
    int data; 
    pDoSomething ds; //<--pointer to DoSomething function 
}foo; 

void DoSomething(foo* this) 
{ 
    this->data++; //<-- C++ compiler won't compile this as C++ compiler uses 'this' as one of its keywords. 
} 

int main() 
{ 
    foo a; 
    a.ds = DoSomething; // you have to set the function. 
    a.data = 0; 
    a.ds(&a);  //this is the same as C++ a.DoSomething code above. 
} 

Наконец, ответ на ваш вопрос ниже код.

void DoSomething(foo* this); 
int main() 
{ 
    DoSomething(??); //WHAT!?? We need to pass something here. 
} 

Посмотрите, вам нужен объект для прохождения. Ответ - нет.

+1

Вы пришли почти через три часа после того, как Джаред показал, как это может произойти, и во втором предложении вы выговариваете, что это невозможно! Я удивлен. – sbi

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