나는 사용자 입력에 따라 비슷한 일을하는 동일한 함수 이름을 가진 두 개의 클래스를 가지고있다. 나는 이런 식으로해야합니다.조건에서 객체를 선언하고 나머지 기능을 통해 사용할 수있게 만드는 방법은 무엇입니까?
if (myapp.advanced == true)
class1 a;
else
class2 a;
그러나 a는 if 내부에서 선언되었으므로 다음 줄에서 사용할 수 없습니다. 위의 조건을 어떻게 수정합니까?
나는 사용자 입력에 따라 비슷한 일을하는 동일한 함수 이름을 가진 두 개의 클래스를 가지고있다. 나는 이런 식으로해야합니다.조건에서 객체를 선언하고 나머지 기능을 통해 사용할 수있게 만드는 방법은 무엇입니까?
if (myapp.advanced == true)
class1 a;
else
class2 a;
그러나 a는 if 내부에서 선언되었으므로 다음 줄에서 사용할 수 없습니다. 위의 조건을 어떻게 수정합니까?
공통 기본 클래스를 사용하여이 작업을 수행합니다 const
참조에 바인드
const base& a = (myapp.advanced == true) ? static_cast<base&>(class1())
: class2();
a.something();
a.some_other_thing();
a.yet_another_thing();
임시직은 자신의 수명이 기준의 수명이 끝날 때까지 연장, 그래서이 안전합니다. 당신이 우려 객체 생성 및 다른 기능에를 사용 객체를 분리하는 경우에는 같은 해커는 (당신이 개체를 수정해야하는 경우 그리고 당신은 멀리 const
과 함께 할 수있는) 필요하지 않을 것입니다 :
void do_something(base& obj)
{
obj.something();
obj.some_other_thing();
obj.yet_another_thing();
}
if (myapp.advanced == true) {
class1 a;
do_something(a);
} else {
class2 a;
do_something(a);
}
종류는 관련이없는 경우에도 함수 템플릿에 do_something()
를 설정하여이 작업을 수행 할 수 있습니다 :
template< class T >
void do_something(T& obj)
{
obj.something();
obj.some_other_thing();
obj.yet_another_thing();
}
if (myapp.advanced == true) {
class1 a;
do_something(a);
} else {
class2 a;
do_something(a);
}
@sbi : 예, 다른 것을 추가했음을 알게 된 다음에는 걱정하지 않아도됩니다. Btw,'class1()'과'class2()'는 같은 타입을 가지고 있지 않기 때문에 3 진 표현식은 캐스트없이 컴파일되지 않습니다. 그 중 하나는'const base &'에 캐스트해야합니다. –
@sgolodetz : 네 말이 맞아, 이것을 지적 해 주셔서 감사합니다! 나는 그것을 고쳤다. – sbi
덧붙여 말하자면, 첫 번째 방법은 객체가'const' 일때 만 작동한다는 것입니다. 임시가 아닌 const 참조에 바인드 할 수 없기 때문입니다. 그러나 그들이 'const'가되는 것이 좋으면, 이것은 좋은 것에 대한 것입니다. –
기본 클래스에는 function something()을 순수 가상으로두고 class1과 class2를 상속하는 것이 좋습니다.
class Base
{
public:
virtual void something() = 0;
virtual ~Base(){}; // since we use Base class pointer the destructor should be virtual
};
class class1 : public Base
{
public:
void something(){ //do stuff
}
};
class class2 : public Base
{
public:
void something(){ //do other stuff
}
};
다음은이 기술의 사용 예제입니다 :
int main()
{
Base* a = NULL;
if (myapp.advanced == true)
a = new class1();
else
a = new class2();
a->something();
// when the instance is not needed anymore destroy it.
delete a;
}
프레드 Nurk이 코멘트에 언급 한 것처럼 delete
연산자를 사용하는 다른 대안있다 - auto_ptr은 다른 부스트 스마트 포인터를. 그들은 많은 사람들 (나 자신 포함)이 널리 사용하여 new
으로 만든 오브젝트의 수명을보다 쉽게 제어 할 수 있습니다. 영업 이익의 코멘트 다음
또 다른 편집
:#ifndef _SOME_UNIQUE_NAME_HERE_
#define _SOME_UNIQUE_NAME_HERE_
// header body goes here
#endif
에서 여러 포함 보호 매크로를 넣어하는 것을 잊지 마십시오. 내가 생각할 수있는
a를 삭제하는 것을 잊지 마십시오. :-) 기본 클래스를 원하지 않으면 두 포인터를 사용하여 동일하게 할 수 있습니다. 그런 다음 NULL이 아닌 값을 통해 무언가를 호출하십시오. –
+1, 이것은 인터페이스 + 2 구체 구현의 주요 후보로 보인다. –
'Base :: something()','class1 :: something()','class2 :: something()'을 public으로 만들고, Base에 가상 소멸자를 추가 할 수 있습니다. –
두 가지 방법 :
1) 클래스 1을 확인하고 Class2의 몇 가지 기본 클래스 classB
에서 파생은, 다음을 수행하십시오
template <typename T> void do_something(T& t)
{
t.something();
}
...
if(myapp.advanced)
{
class1 a;
do_something(a);
}
else
{
class2 a;
do_something(a);
}
:
shared_ptr<classB> a;
if(myapp.advanced == true) a.reset(new class1);
else a.reset(new class2);
a->something();
2) 템플릿 함수를 작성
기본 클래스를 추가하기 위해 class1
및 class2
을 변경할 수없는 경우 두 번째 방법이 더 적합합니다. 또한 do_something
내부의 비트가 해당 객체의 something()
을 호출하는 것보다 더 복잡하다고 가정합니다. 그렇지 않으면 그냥 직접 호출 할 수 있습니다!
편집 : 두 번째 방법은 문제의 나머지 기능에서 사용할 수 있도록하지 않습니다. 대신 사용할 수있는 새로운 기능이 추가됩니다.
코딩 논리에 따라 Class1과 Class2는 공통점이 있습니다. 공통 기본 클래스에서 코드를 파생시켜 코드에 표현하십시오. 그런 다음 기본 클래스 포인터를 사용하여 파생 클래스의 인스턴스를 보유합니다.
이 접근하는 방법에는 여러 가지가 있지만 추가 정보없이 아마 당신이 할 조언 것이다 : 나는 수업 자료라는 공통 조상이 있다고 가정
을 물론
Base* a;
if (myapp.advanced == true)
a = new class1();
else
a = new class2();
당신은하지 않아야 더 이상 필요하지 않거나 스마트 포인터를 사용하면 delete
을 발급해야합니다.
if-else 문을 반복해서 사용하는 경우이 절차는 일종의 함수 또는 팩토리 클래스로 래핑하는 것이 더 좋을 수 있지만 상황에 따라 다릅니다. 이러한 유형이 관련된 경우
는else 브랜치의 경우'a = new class2;'를 의미합니다 :) –
예, 물론 고마워요. – Palmik
는'm의 값입니다 yapp.advanced'는 컴파일 타임에 알려진가요? –
@Steve : 아니요, 프로그램을 실행할 때 사용자가 설정합니다. – thorvald
'if (myapp.advanced) ' –