C ++에서 초기화하기 전에 객체를 선언합니다
-
03-07-2019 - |
문제
C ++에서 변수를 인스턴스화하지 않고 선언 할 수 있습니까? 나는 다음과 같은 일을하고 싶다 :
Animal a;
if( happyDay() )
a( "puppies" ); //constructor call
else
a( "toads" );
기본적으로, 나는 단지 조건부 외부를 선언하여 올바른 범위를 얻고 싶습니다.
포인터를 사용하고 할당하지 않고이 작업을 수행 할 수있는 방법이 있습니까? a
힙에? 참조로 영리한 것이 있습니까?
해결책
기본 생성자로 정의 할 때 객체가 구성되므로 C ++에서 직접 할 수 없습니다.
그러나 시작하여 매개 변수화 된 생성자를 실행할 수 있습니다.
Animal a(getAppropriateString());
또는 실제로와 같은 것을 사용할 수 있습니다 ?: operator
올바른 문자열을 결정합니다. (업데이트 : @Greg는 이것에 대한 구문을 주었다. 그 답을 참조하십시오)
다른 팁
생성자를 호출하지 않고는 변수를 선언 할 수 없습니다. 그러나 예에서는 다음을 수행 할 수 있습니다.
Animal a(happyDay() ? "puppies" : "toads");
범위를 벗어나 자마자 참조를 사용할 수 없습니다. 참조는 삭제 될 객체를 가리 킵니다.
실제로 여기에는 두 가지 선택이 있습니다.
1- 포인터와 함께 이동 :
Animal* a;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
// ...
delete a;
2- init 메소드를 추가하십시오 Animal
:
class Animal
{
public:
Animal(){}
void Init( const std::string& type )
{
m_type = type;
}
private:
std:string m_type;
};
Animal a;
if( happyDay() )
a.Init( "puppies" );
else
a.Init( "toads" );
나는 개인적으로 옵션 2와 함께 갈 것입니다.
나는 Greg의 대답을 선호하지만 이것도 할 수 있습니다.
char *AnimalType;
if( happyDay() )
AnimalType = "puppies";
else
AnimalType = "toads";
Animal a(AnimalType);
조건부 운영자가 금지 된 장소에서 일했기 때문에 이것을 제안합니다. (한숨!) 또한, 이것은 두 가지 대안을 넘어서 매우 쉽게 확장 될 수 있습니다.
쓰레기 수집을 피하려면 스마트 포인터를 사용할 수 있습니다.
auto_ptr<Animal> p_a;
if ( happyDay() )
p_a.reset(new Animal( "puppies" ) );
else
p_a.reset(new Animal( "toads" ) );
// do stuff with p_a-> whatever. When p_a goes out of scope, it's deleted.
여전히 사용하려는 경우. -> 대신 구문은 위의 코드 후에이를 수행 할 수 있습니다.
Animal& a = *p_a;
// do stuff with a. whatever
Greg Hewgill의 답변 외에도 몇 가지 다른 옵션이 있습니다.
코드의 본체를 함수로 들어 올립니다.
void body(Animal & a) {
...
}
if( happyDay() ) {
Animal a("puppies");
body( a );
} else {
Animal a("toad");
body( a );
}
(ab) 배치 사용 New :
struct AnimalDtor {
void *m_a;
AnimalDtor(void *a) : m_a(a) {}
~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};
char animal_buf[sizeof(Animal)]; // still stack allocated
if( happyDay() )
new (animal_buf) Animal("puppies");
else
new (animal_buf) Animal("toad");
AnimalDtor dtor(animal_buf); // make sure the dtor still gets called
Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on
가장 좋은 작업은 포인터를 사용하는 것입니다.
Animal a*;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
예, 다음을 수행 할 수 있습니다.
Animal a;
if( happyDay() )
a = Animal( "puppies" );
else
a = Animal( "toads" );
그것은 생성자를 올바르게 호출합니다.
편집 : 한 가지를 잊어 버렸습니다 ... A를 선언 할 때는 아무것도하지 않는 생성자이든 여전히 값을 초기화하는지 여부에 관계없이 생성자를 여전히 호출해야합니다. 따라서이 메소드는 초기화시 하나와 IF 문 안에있는 두 개의 객체를 만듭니다.
더 나은 방법은 클래스의 init () 함수를 작성하는 것입니다.
Animal a;
if( happyDay() )
a.init( "puppies" );
else
a.init( "toads" );
이 방법은 더 효율적입니다.